【问题标题】:How to "select until" a sum is reached如何“选择直到”达到总和
【发布时间】:2008-11-13 16:00:58
【问题描述】:

我正在寻找一种方法来选择,直到达到总和。

我的“文档”表有“tag_id”和“size”字段。

我想选择所有带有tag_id = 26 的文档,但我知道我只能处理 600 个单位的大小。因此,当我知道前 10 个文档加起来已经超过 600 个单位时,选择 100 个文档并丢弃其中的 90 个是没有意义的。

因此,目标是:当我要丢弃大部分数据时,不要带回大量数据进行解析。

...但我也很想避免在这个应用程序中引入使用光标的工作。

我正在使用 MySQL。

【问题讨论】:

  • MySQL有解析功能吗?
  • 既然会有很多文档组合加到> 600,那么你怎么知道你要使用哪些文档呢?还是没关系?
  • 优先考虑最近添加的文档(有一个 date_created 字段,我们将对其进行排序)
  • 这听起来像是与数据库接口的业务逻辑/组件/代码的工作,而不是查询本身的工作。
  • Matt... 通过分析,可以在查询中完成。如果可以在数据库中完成会更快。

标签: mysql sql


【解决方案1】:

当加起来达到最大单位时,您需要某种方式来排序哪些记录优先于其他记录。否则,您怎么知道您保留了哪一组总计多达 600 条的记录?

SELECT d.id, d.size, d.date_created
FROM documents d
INNER JOIN documents d2 ON d2.tag_id=d.tag_id AND d2.date_created >= d.date_created
WHERE d.tag_id=26
GROUP BY d.id, d.size, d.date_created
HAVING sum(d2.size) <= 600
ORDER BY d.date_created DESC

这只是一个让您入门的基本查询,还有许多问题需要解决:

  • 它在
  • 它不会在以后检查其他可能仍适合上限的较小记录。
  • 具有相同 date_created 值的记录可能会在这里和那里进行“双重计算”。

【讨论】:

    【解决方案2】:

    这效率要低得多,但它确实避免了光标(假设您的文档表也有一个序列号列):

    select a.id, (select sum(b.size) from documents b where b.id <= a.id and b.tag_id = 26)
    from documents a
    where a.tag_id = 26
    order by a.id
    

    另外,这是在 pgsql 中完成的,所以我不确定这个确切的语法是否适用于 mysql。

    然后您可以将其包装在另一个查询中,该查询查找总和 > 600 的那些(您必须命名总和列)并获取第一个 id。然后处理下面的所有 id,包括那个。

    【讨论】:

    • 呃,如果没有id,则使用创建的时间戳。
    【解决方案3】:

    您必须首先将文档存储在表变量中,按照您想要检索它们的顺序对它们进行排序,然后使用累积值更新每一行,以便您可以对其进行选择。

     declare @documents_temp table (
        tag_id int,
        size int,
        cumulative_size int null)
    
    insert into @documents_temp
    select tag_id, size, size from documents order by tag_id
    
    update @documents_temp d set d.cumulative_size = d.size + 
        (select top 1 cumulative_size from @documents_temp 
         where tag_id < d.tag_id order by tag_id desc)
    
    select tag_id, size from @documents_temp where cumulative_size <= 600
    

    不知道值不值得。

    【讨论】:

      猜你喜欢
      • 2020-05-31
      • 2019-03-16
      • 2012-05-19
      • 2013-01-08
      • 1970-01-01
      • 2020-03-28
      • 1970-01-01
      • 2023-02-09
      • 2023-04-01
      相关资源
      最近更新 更多