选择n个第一个元素,使累计和达到给定值

时间:2016-09-25 01:29:29

标签: sql postgresql

从PostgreSQL查询开始

SELECT filename FROM files_storage ORDER BY date;

我想将输出表减少到第一行 n 行,以便从名为size的列的第1行到 n 的累计和达到至少max_value

示例:

date         filename   size
2016-09-01   /a/aaa/    20
2016-09-02   /a/bbb/    70
2016-09-03   /a/ccc/    20
2016-09-04   /a/ddd/    30
2016-09-05   /a/eee/    50

如果max_value为100,我想返回前三行,因为20 + 70 + 20 >= 100

我在这里看到了类似问题的答案,但在PostgreSQL中没有。

2 个答案:

答案 0 :(得分:2)

这是我的看法:

SELECT filename, size
FROM (
    SELECT
        filename,
        size,
        coalesce(sum(size) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS sum
    FROM files_storage
) t
WHERE sum<100

我在这里使用sum作为窗口函数来计算每个文件,所有先前文件(不包括当前文件)的大小总和。然后我根据该数字是否小于阈值来过滤行。从总和中排除当前文件可确保我们将获得更多行,这将是提示总和超过阈值的文件。

答案 1 :(得分:0)

使用累积和功能:

SELECT fs.*
FROM (SELECT fs.*, SUM(size) OVER (ORDER BY date) as running_sum
      FROM files_storage
     ) fs
WHERE running_sum >= 100 AND running_sum - size < 100;

哦,这是第一行跨越边界。

你想要所有这些,所以相反:

SELECT fs.*
FROM (SELECT fs.*, SUM(size) OVER (ORDER BY date) as running_sum
      FROM files_storage
     ) fs
WHERE running_sum - size < 100;

如果您可以拥有重复日期,并且当同一日期的重复值可能适用时,任意想要一个值:

SELECT fs.*
FROM (SELECT fs.*,
             SUM(size) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as running_sum
      FROM files_storage
     ) fs
WHERE running_sum - size < 100;