某库表的前 4 个字段都可以是分组字段。
ID | SPLIT | CUST | DATE | AMOUNT |
ID_1 | SPLIT_YES | A | 2024-05-01 00:00:00 | 100 |
ID_1 | SPLIT_NO | A | 2024-04-01 00:00:00 | 200 |
ID_1 | SPLIT_YES | B | 2024-03-01 00:00:00 | 50 |
ID_2 | SPLIT_YES | A | 2024-05-01 00:00:00 | 50 |
ID_2 | SPLIT_NO | A | 2024-04-01 00:00:00 | 300 |
ID_2 | SPLIT_NO | B | 2024-03-01 00:00:00 | 300 |
ID_3 | SPLIT_YES | B | 2024-04-01 00:00:00 | 90 |
ID_3 | SPLIT_NO | B | 2024-04-01 00:00:00 | 30 |
ID_3 | SPLIT_NO | A | 2024-04-01 00:00:00 | 10 |
ID_3 | SPLIT_NO | A | 2024-03-01 00:00:00 | 10 |
现在先按前 2 个字段 ID、SPLIT 分组,再根据条件决定是否继续二次分组:如果组内的日期 DATE 无重复,则保留本组日期最近的那条记录,并将 AMOUNT 替换为本组的 AMOUNT 之和;如果组内的日期有重复,则将本组记录再按 CUST 分组,同样保留当前小组日期最近的那条记录,同样将 AMOUNT 替换为当前小组的 AMOUNT 之和。
SQL分组后必须立刻汇总,不能保留分组子集,间接实现的代码比较复杂。SPL 可以保留子集继续计算,子集也可以继续分组:esProc Web Try
A | |
1 | $select * from test_table_mm.txt order by DATE desc |
2 | =A1.group(ID,SPLIT) |
3 | =A2.conj(if(~.icount(DATE)==~.count(), [~], ~.group(CUST))) |
4 | =A3.(~(1).run(AMOUNT=A3.~.sum(AMOUNT))) |
A1:加载数据,日期近的记录排在前面。
A2:用 group 函数按前 2 个字段分组,但不汇总,每组是一个集合。如图是第 1 组和第 5 组。
A3:(if(~.icount(DATE)==~.count(), [~], ~.group(CUST))),处理每组数据,如果本组日期没有重复,则返回当前组,比如第 1 组;否则将当前组按 CUST 继续分组,返回每个小组,也就是集合的集合,比如第 5 组。~ 表示当前组。函数 icount 用于统计不重复的成员数量。函数 count 用于统计成员数量。[]是集合符号,因为 ~ 本身是集合,所以 [~] 是集合的集合,这样处理可以使数据结构前后一致,方便统一处理。如图是第 1 组和第 5 组。
conj(…),合并处理后的各组数据,让每组数据从 2 层集合(集合的集合)上升为单层集合。其中,原第 5 组因为继续分组,有 2 个集合的集合,合并后上升为 2 个集合:
A4:统一处理 A3 的各组数据:取当前组的第 1 条记录,将 AMOUNT 替换为当前组的 AMOUNT 之和。(1) 表示集合的第 1 个成员。
esProc开源免费的,下载使用~~