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