gpt4 book ai didi

postgresql - Postgres - 根据另一列的总和结果计算总和

转载 作者:行者123 更新时间:2023-11-29 12:02:30 24 4
gpt4 key购买 nike

我正在使用 Postresql 9.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

假设的中间结果(只是为了理解我的期望):

id         sum(count)  discrete volume
1 5 12
2 11 26
3 13 37
4 23 46
5 28 60
6 45 79
7 45 87
8 57 91
9 75 97
10 87 111
11 10 10 (reset since volume >= 100)
12 25 17
13 33 29
14 35 46
15 40 76
16 49 100
17 2 16.5 (reset since volume >= 100)

预期最终结果:

sum(count) discrete volume
87 111
49 100
2 16.5 (partial result, which is desired)

到目前为止我已经尝试过:SQL Fiddle

我对 SQL Fiddle 中显示的当前查询有了想法来自 another StackOverflow answer这显然不能正常工作(但是对于我试图解决的另一个问题,它工作得很好)。我从 different StackOverflow answer 看到我可能想使用递归查询(PostgreSQL Documentation),但我不知道如何正确编写查询才能正常工作:(

我当然可以用 Java 代码编写它(并且已经这样做了),但我想用 SQL 来完成它,因此它有望比读取所有行和计算结果更快。我也很可能会编写一个存储过程来完成这项工作,但我宁愿避免这种情况,因为我正在使用 JPA(在本例中使用 native 查询)并希望将所有代码保存在同一个地方( Java 代码库)。另外,我希望能够动态地包含/排除列,所以我想用 Java 代码构造查询(实际表的列比我的示例多得多)。

感谢您提供的任何帮助。

编辑:

感谢@klin 的评论并查看引用的 StackOverflow 问题,我离这个目标越来越近了。这是我所拥有的(生成中间结果):

WITH RECURSIVE WorkTable(id, count_sum, volume_sum) AS 
(
SELECT
id,
count AS count_sum,
volume AS volume_sum
FROM measurements
WHERE id = 1
UNION ALL
SELECT
measurements.id,
CASE WHEN WorkTable.volume_sum >= 100
THEN measurements.count
ELSE WorkTable.count_sum + measurements.count
END AS count_sum,
CASE
WHEN WorkTable.volume_sum >= 100
THEN measurements.volume
ELSE WorkTable.volume_sum + measurements.volume
END AS discrete_sum_volume
FROM measurements
JOIN WorkTable
ON measurements.id = WorkTable.id + 1
)
SELECT *
FROM WorkTable
ORDER BY id

但是,我仍然缺少的是如何获得最终结果。如果我使用 WHERE volume_sum >= 100 我得不到最终(部分)结果。而且我不能使用 OR id = MAX(id) 因为 Postgres 不允许在 WHERE 子句中使用它。

编辑: 顺便说一句,在@klin 和@JorgeCampos 花费了所有的工作和时间来查看和回答我的问题之后,我发现此查询无法针对具有数百万行的表执行。我创建了一个存储过程;我不想去那里,但似乎没有其他表现良好的选择。对于大型表,存储过程的性能优于 RECURSIVE 查询许多数量级。

最佳答案

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

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)

SqlFiddle.

关于postgresql - Postgres - 根据另一列的总和结果计算总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49947095/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com