bad*_*era 3 postgresql aggregate
我有一个包含金额列和索引列的表。我希望构建一个查询,它总结了从给定开始索引到结束索引的每个结果间隔的给定间隔范围的数量 - 即“间隔范围”根据索引列对数据进行切片。对于这些组,将构建金额总和。
这是可能的吗?
SELECT sum(amount) from mytable
WHERE index between <startindex> and <endindex>
GROUP BY ...
Run Code Online (Sandbox Code Playgroud)
例子:
amount | index
55 1
88 5
45 6
86 7
87 10
88 11
57 16
58 17
59 20
60 21
Run Code Online (Sandbox Code Playgroud)
间隔范围为 5、起始索引 5 和结束索引 14 的查询应产生两个返回值:
88+45+86 => 219
87+88 => 175
Run Code Online (Sandbox Code Playgroud)
间隔范围为 4、起始索引 0 和结束索引 15 的查询应产生四个返回值:
55 => 55
88+45+86 => 219
87+88 => 175
-- => 0
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助!
CREATE TABLE T(amount INT, index INT);
INSERT INTO T VALUES
(55, 1),(88, 5),(45, 6),(86, 7),(87, 10),
(88, 11),(57, 16),(58, 17),(59, 20),(60, 21);
Run Code Online (Sandbox Code Playgroud)
您可以利用 Postgres 函数generate_series()。
generate_series(start, stop, step)
Run Code Online (Sandbox Code Playgroud)
生成一系列值,从开始到停止,步长为 step
下面的示例使用从 0 到 14 的序列,间隔为 4。
SELECT generate_series(0, 14, 4) Serie;
| serie |
| ----: |
| 0 |
| 4 |
| 8 |
| 12 |
WITH CTS AS
(
SELECT generate_series(0, 14, 4) Serie
)
SELECT COALESCE(SUM(T.amount),0) AS amount, CTS.Serie
FROM CTS
LEFT JOIN T
ON T.index >= CTS.Serie
AND T.index < CTS.Serie + 4
GROUP BY CTS.Serie
ORDER BY CTS.Serie;
amount | serie
-----: | ----:
55 | 0
219 | 4
175 | 8
0 | 12
Run Code Online (Sandbox Code Playgroud)
您可以使用允许您使用参数的用户定义函数
Run Code Online (Sandbox Code Playgroud)CREATE OR REPLACE FUNCTION GroupIntervals(low int, high int, step int) RETURNS TABLE (amount int, interv int) AS $$ BEGIN RETURN QUERY WITH CTS AS ( SELECT generate_series(low, high, step) Serie ) SELECT COALESCE(SUM(T.amount),0)::int AS amount, CTS.Serie as interv FROM CTS LEFT JOIN T ON T.index >= CTS.Serie AND T.index < CTS.Serie + step GROUP BY CTS.Serie ORDER BY CTS.Serie; END; $$ LANGUAGE plpgsql;?
Run Code Online (Sandbox Code Playgroud)SELECT * FROM GroupIntervals(0, 14, 4);金额 | 采访 -----: | -----: 55 | 0 第219话 4 175 | 8 0 | 12
Run Code Online (Sandbox Code Playgroud)SELECT * FROM GroupIntervals(5, 14, 5);金额 | 采访 -----: | -----: 第219话 5 175 | 10
dbfiddle在这里
更新
正如Evan Carrol在评论中指出的那样,您可以避免使用 CTE 并将函数语言从 plpgsql 更改为纯 SQL。
Run Code Online (Sandbox Code Playgroud)CREATE OR REPLACE FUNCTION GroupIntervals(low int, high int, step int) RETURNS TABLE (amount int, interv int) AS $$ SELECT COALESCE(SUM(T.amount),0)::int AS amount, CTS.Serie as interv FROM generate_series(low, high, step) AS CTS(Serie) LEFT JOIN T ON index >= CTS.Serie AND index < CTS.Serie + step GROUP BY CTS.Serie ORDER BY CTS.Serie; $$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)SELECT * FROM GroupIntervals(0, 14, 4);金额 | 采访 -----: | -----: 55 | 0 第219话 4 175 | 8 0 | 12
Run Code Online (Sandbox Code Playgroud)SELECT * FROM GroupIntervals(5, 14, 5);金额 | 采访 -----: | -----: 第219话 5 175 | 10
dbfiddle在这里
| 归档时间: |
|
| 查看次数: |
1313 次 |
| 最近记录: |