Postgresql Postgres-根据另一列的总和计算总和

Postgresql Postgres-根据另一列的总和计算总和,postgresql,Postgresql,我正在使用PostResql9.6,并试图弄清楚如何创建一个查询,根据不同列(都在同一个表中)的离散和计算列的和。例如,我需要每组行的计数总和,直到卷>=100,然后重新开始计算计数总和 示例数据: id count volume 1 5 12 2 6 14 3 2 11 4 10 9 5

我正在使用PostResql9.6,并试图弄清楚如何创建一个查询,根据不同列(都在同一个表中)的离散和计算列的和。例如,我需要每组行的计数总和,直到卷>=100,然后重新开始计算计数总和

示例数据:

id          count       volume
1           5           12
2           6           14
3           2           11
4           10          9
5           5           14
6           17          19
7           0           8
8           12          4
9           18          6
10          12          14
11          10          10
12          15          7
13          8           12
14          2           17
15          5           30
16          9           24
17          2           16.5
假设的中间结果(只是为了理解我的预期):

预期最终结果:

sum(count) discrete volume
87         111
49         100
2          16.5   (partial result, which is desired)
到目前为止,我所尝试的:

我对from中显示的当前查询有了想法,这显然不能正常工作(但是对于我试图解决的另一个问题,它工作得非常好)。我从a中看到,我可能希望使用递归查询(),但我无法确切地知道如何正确编写查询,使其正常工作:(

我当然可以用Java代码编写它(现在已经有了),但我想用SQL来编写它,所以希望它比读取所有行和计算结果更快。我也很可能编写一个存储过程来实现这一点,但我更希望避免这种情况,因为我使用的是JPA(在本例中是本机查询)而且,我希望能够动态地包含/排除列,因此我希望用Java代码构造查询(实际表的列比我的示例多得多)

谢谢你能给我的帮助

编辑:

感谢@klin的评论并查看引用的StackOverflow问题,我离此越来越近了。以下是我得到的(生成中间结果):

然而,我仍然缺少的是如何获得最终结果。如果我使用
WHERE volume\u sum>=100
我不会得到最终(部分)结果。我不能使用
或id=MAX(id)
,因为Postgres在WHERE子句中不允许这样做


编辑:顺便说一句,@klin和@JorgeCampos花了这么多时间研究和回答我的问题,我发现这个查询对一个有数百万行的表不起作用。我创建了一个存储过程;我不想去那里,但似乎没有其他性能良好的替代方法。stored过程对一个大表执行多个数量级的递归查询。

我使用了
行计数()
,因为需要连续的行号。您不应该依赖主键,因为它通常可能包含空格

with recursive cte as (
    select *, row_number() over (order by id)
    from measurements
),
work_table as (
    select 
        id,
        count as count_sum,
        volume as volume_sum,
        row_number
    from cte
    where row_number = 1
    union all
    select
        c.id,
        case when w.volume_sum >= 100
            then c.count
            else w.count_sum + c.count
        end as count_sum,
        case
            when w.volume_sum >= 100
            then c.volume
            else w.volume_sum + c.volume
        end as discrete_sum_volume,
        c.row_number
    from cte c
    join work_table w
    on c.row_number = w.row_number + 1
)
select count_sum, volume_sum
from work_table
where volume_sum >= 100
or id = (select max(id) from work_table)
order by id
结果:

 count_sum | volume_sum 
-----------+------------
        87 |        111
        49 |        100
         2 |       16.5
(3 rows)

你的意思是
直到volume@JorgeCampos-我试着根据你的问题编辑这个问题,它看起来不太清楚。重置条件是
volume>=100
有两种方法可以解决类似的问题-迭代和递归。这两种方法的示例都可以在这个线程@klin中找到,感谢你的回答。ite推理方法似乎需要一个我正试图避免的存储过程(原因请参见问题的正文)。如果可能的话,我想要一个递归解决方案(我不确定)。我已经对递归查询进行了整整一天的黑客攻击,但到目前为止,我所尝试的一切都不起作用。对于您当前的尝试,解决方案是基于该case语句创建一个行号,并仅获取number=1的行,但是您在查询中假设ID上没有间隙,我尤其不同意我的观点t、 任何对该表的删除或手动插入都会完全破坏您的功能。非常感谢!我拥有所有(或至少大部分)功能,但在阅读文档、破解SQL和处理其他问题(当我被破坏时,我很难集中精力:)之间,我无法将所有功能整合在一起。使用
row\u number()
id=(从work\u表中选择max(id)
部分WHERE是非常有价值的输入。我很高兴我能提供帮助。惊人的答案+1.
with recursive cte as (
    select *, row_number() over (order by id)
    from measurements
),
work_table as (
    select 
        id,
        count as count_sum,
        volume as volume_sum,
        row_number
    from cte
    where row_number = 1
    union all
    select
        c.id,
        case when w.volume_sum >= 100
            then c.count
            else w.count_sum + c.count
        end as count_sum,
        case
            when w.volume_sum >= 100
            then c.volume
            else w.volume_sum + c.volume
        end as discrete_sum_volume,
        c.row_number
    from cte c
    join work_table w
    on c.row_number = w.row_number + 1
)
select count_sum, volume_sum
from work_table
where volume_sum >= 100
or id = (select max(id) from work_table)
order by id
 count_sum | volume_sum 
-----------+------------
        87 |        111
        49 |        100
         2 |       16.5
(3 rows)