从 SPL 到 SQL:灵活区间汇总
Oracle 数据库某表的 id 字段的范围是整数 1-2000。
id | value |
1 | 10 |
1 | 11 |
2 | 100 |
3 | 5 |
3 | 9 |
20 | 0 |
21 | 1000 |
22 | 2000 |
1000 | 1 |
1000 | 20 |
现在要对 id 按多个连续的区间进行分组,对组内的 value 进行求和,计算结果按区间顺序排列。区间是数字序列的形式,可以灵活修改。比如数字序列是 10,20,100,1000,2000 时,表示将 id 按 1-10、11-20、21-100、101-1000、1001-2000 的区间进行分组汇总。注意分组字符串的起始值的格式是:数字序列的成员 +1
IDs_range | sum_of_values |
1-10 | 135 |
11-20 | 0 |
21-100 | 3000 |
101-1000 | 21 |
SQL:
WITH id_ranges (min_value, max_value) AS (
SELECT LAG(COLUMN_VALUE, 1, 0) OVER (ORDER BY COLUMN_VALUE) + 1,
COLUMN_VALUE
FROM TABLE(SYS.ODCINUMBERLIST(10,20,100,1000,2000))
)
SELECT r.min_value || '-' || r.max_value AS id_range,
SUM(value) AS sum_of_values
FROM dummy_data d
INNER JOIN id_ranges r
ON d.id BETWEEN r.min_value AND r.max_value
GROUP BY r.min_value, r.max_value
order by r.min_value
SQL 没有提供求某个值在哪个区间的函数,不能直接按区间分组,要绕大弯造个临时的区间表,关联后再分组汇总,结构比较复杂。
SPL 代码要简单易懂很多: https://try.esproc.com/splx?3KN
A | |
1 | $select * from dummy_data.txt order by id |
2 | =list=[10,20,100,1000,2000] |
3 | =A1.groups@u(list.pseg@r(id):IDs_range; sum(value):sum_of_values) |
4 | =A3.run(IDs_range=(ifn(list.m(IDs_range),0)+1) / "-" / list.m(IDs_range+1)) |
A1:加载数据。
A3:直接按区间分组汇总,函数 pseg 返回某个值所在的区间序号,不需要造表,也不用关联,@r 表示左开右闭。
A4:将分组号改成指定的字符串格式。
英文版 https://c.esproc.com/article/1737366859772