从 SQL 到 SPL:按次序做区间数据的去重计数

teradata 库表有 3 个字段,日期、账号、账号购买的商品名称。

Date

ACCOUNT

NAME

2024-01-01

A

XOXO

2024-01-02

A

XOXO

2024-01-02

A

OXXO

2024-01-04

A

XOOX

2024-01-05

A

OOXO

2024-01-06

A

XOXO

2024-01-01

B

B11

2024-01-02

B

B21

2024-01-02

B

B21

2024-01-02

B

B22

2024-01-02

B

B11

2024-01-03

B

B31

2024-01-01

C

C1

2024-01-02

C

C1

2024-01-03

C

C1

现在要计算出每个账号到每天之前曾经购买过多少种商品,也就是从开始到上一日购买过的不同的商品的数量。

Date

ACCOUNT

COUNT_DISTINCT_NAME

2024-01-01

A

Null

2024-01-02

A

1

2024-01-04

A

2

2024-01-05

A

3

2024-01-06

A

4

2024-01-01

B

Null

2024-01-02

B

1

2024-01-03

B

3

2024-01-01

C

null

2024-01-02

C

1

2024-01-03

C

1

ACCOUNT分组,再按日期分组,依次处理每组,按区间取第一组到当前组,并进行去重和计数。但 SQL 分组必须伴随聚合,而不能保持分组子集做进一步处理;这时候就要转换思路,设置各种标记来过渡,写成多层嵌套语句反复遍历数据表才能计算出来。

SPL允许分组时保持分组子集,以进一步处理。SPL 的跨行引用也比窗口函数要简洁很多:


 A

1

=teraJDBC.query("select * from tb”)

2

=A1.group(ACCOUNT)

3

=A2.conj(~.group(Date;ACCOUNT,~[:-1].conj().icount(NAME):COUNT_DISTINCT_NAME))

4

=A3.run(if(#3==0,#3=null))

A1:通过JDBC加载数据。

A2:按账号分组。

A3:处理A2的每组数据:继续按日期分组,处理每日数据,取从开始到上一日的各小组数据,合并各小组,求不同商品名称的数量。最后合并各大组的处理结果。[:-1]表示从第一个成员直到上一个成员的集合,函数icount用于去重计数,即count(distinct)

A4:将第3列中的0改为null

问题来源:https://stackoverflow.com/questions/78344447/get-the-distinct-names-an-account-has-prior-the-last-day-in-teradata-or-oracle-w