从 SQL 到 SPL:分组后计算相邻子集的交集数量

某库表记录了一个项目的执行情况,每天有多人参与项目,一个人可以在一天里参与项目的多个任务。

EMP_ID

EMP_DATE

EMP_TASK

A1

04-01-2024

345

A2

04-01-2024

546

A3

04-01-2024

232

A4

04-01-2024

8000

A5

04-01-2024

2344

A1

04-02-2024

456

A2

04-02-2024

9280

A3

04-02-2024

324

A2

04-02-2024

754

A8

04-02-2024

75

A2

04-03-2024

400

A3

04-03-2024

234

A3

04-04-2024

100

现在要计算出:每天还有几个人是昨天参与过项目的。也就是按日期分组后,计算每日与上一日的人员的交集的数量。第一天是特殊的,要假设全员上一日都参加了项目。

EMP_DATE

COUNT

04-01-2024

5

04-02-2024

3

04-03-2024

2

04-04-2024

1

可以先按日期分组,再对分组子集进行交集运算,这就要求在分组后保持子集。但 SQL 分组后必须立刻汇总,无法保持子集,计算交集也无从谈起。要反过来按人分组,判断每个人在某日期和上一日是否同时出现过,然后再对这些日期分组汇总,会涉及多层嵌套和窗口函数,非常麻烦。

SPL 分组后可以保持子集,也支持引用相邻子集,可以按思路直接写出代码。


 A

1

=dbConn.query("select distinct EMP_ID,EMP_DATE from tb")

2

=A1.group(EMP_DATE)

3

=A2.new(EMP_DATE,if(#==1,~.len(),(~.(EMP_ID)^~[-1].(EMP_ID)).len()):COUNT)

A1:从数据库加载数据,对 EMP_ID 去重

A2:按日期分组,但不汇总。

A3:根据分组结果新建二维表。如果当前组是第 1 组,直接返回组内成员数量;如果不是第 1 组,则求当前组和上一组的 EMP_ID 的交集,再求成员数量。^ 用于求交集,[-1] 表示上一组。

问题来源:https://stackoverflow.com/questions/78324132/how-do-i-perform-recursive-search-in-oracle