SPL:复杂静态转置
转置功能常用报表等前端展现,将查询出来的数据转置成指定的显示格式。比如行转列,列转行,以及比较复杂的动态转置等等。在《SPL:静态转置》一文中,我们为大家介绍了静态转置。但是有些时候,虽然转置后的表结构是可以确定的,但是很难用 pivot 函数直接实现。接下来我们一起看一下,对于这些复杂的静态转置,SPL 是如何处理的。
1. 多行转多行
【例 1】 根据打卡记录,整理员工每日的外出数据。在日常考勤信息表中,每卡每天有 7 条数据:
PER_CODE |
IN_OUT |
DATE |
TIME |
TYPE |
1110263 |
1 |
2013-10-11 |
09:17:14 |
In |
1110263 |
6 |
2013-10-11 |
11:37:00 |
Break |
1110263 |
5 |
2013-10-11 |
11:38:21 |
Return |
1110263 |
0 |
2013-10-11 |
11:43:21 |
NULL |
1110263 |
6 |
2013-10-11 |
13:21:30 |
Break |
1110263 |
5 |
2013-10-11 |
14:25:58 |
Return |
1110263 |
2 |
2013-10-11 |
18:28:55 |
Out |
… |
… |
… |
… |
… |
期望得到如下格式结果:
PER_CODE |
DATE |
IN |
OUT |
BREAK |
RETURN |
1110263 |
2013-10-11 |
9:17:14 |
18:28:55 |
11:37:00 |
11:38:21 |
1110263 |
2013-10-11 |
9:17:14 |
18:28:55 |
13:21:30 |
14:25:58 |
… |
… |
… |
… |
… |
… |
虽然转置后的表结构是可以确定的,但是用函数 A.pivot()实现起来会很复杂。这时可以先创建目标数据结构,再填充数据。首先我们按照期望的结构创建一个空表。然后将数据排序,每 7 条记录分为一组,每组的成员取 [1,7,2,3,1,7,5,6],即要生成的 2 条记录的时间值。最后再按目标结构顺序填入数据即可。
SPL 脚本如下:
A |
|
1 |
=create(PER_CODE,DATE,IN,OUT,BREAK,RETURN) |
2 |
=T("DailyTime.txt").sort(PER_CODE,DATE,TIME) |
3 |
=A2.group((#-1)\7).(~([1,7,2,3,1,7,5,6])) |
4 |
>A1.record(A3.conj([~.PER_CODE,~.DATE]|~.(TIME).m([1,2,3,4])|[~.PER_CODE,~.DATE]|~.(TIME).m([5,6,7,8]))) |
A1:根据目标结构创建空表。
A2:导入日常打卡记录,并按员工号和日期时间排序。
A3:每 7 条记录为一组,每组按指定顺序([1,7,2,3,1,7,5,6])返回记录。
A4:将所有的记录数据按目标顺序合并,再添加到 A3 创建的表中。
2. 行转列同时行间计算
【例 2】 根据用户支付明细表,统计各个用户 2014 年每月应付金额的汇总表。部分数据如下:
ID |
CUSTOMERID |
NAME |
UNPAID |
ORDER_DATE |
112101 |
C013 |
CA |
12800 |
2014/02/21 |
112102 |
C013 |
CA |
3500 |
2014/06/15 |
112103 |
C013 |
CA |
2600 |
2015/03/21 |
112104 |
C025 |
BK |
4600 |
2014/06/11 |
112105 |
C002 |
TUN |
23100 |
2014/01/22 |
112106 |
C002 |
TUN |
13800 |
2014/08/03 |
… |
… |
… |
… |
… |
期望得到如下格式结果:
NAME |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
TUN |
23100 |
23100 |
23100 |
23100 |
23100 |
23100 |
23100 |
13800 |
13800 |
13800 |
13800 |
13800 |
CA |
12800 |
12800 |
12800 |
12800 |
3500 |
3500 |
3500 |
3500 |
3500 |
3500 |
3500 |
|
BK |
4600 |
4600 |
4600 |
4600 |
4600 |
4600 |
4600 |
|||||
… |
对于复杂静态转置,我们还是先创建目标数据结构,再填充数据。
SPL 脚本如下:
A |
|
1 |
=create(NAME,${12.concat@c()}) |
2 |
=T("UserPayment.txt").select(year(ORDER_DATE)==2014).group(CUSTOMERID) |
3 |
>A2.((m12=12.(null),~.(m12(month(ORDER_DATE))=UNPAID), m12.(~=ifn(~,~[-1])),A1.record(NAME|m12))) |
A1:根据目标结构创建空表。
A2:导入 2014 年用户支付明细表,并按客户 ID 分组。
A3:循环每组数据,对成员再进行循环,计算每个月的应付金额,最后和客户名称一起添加到 A1 创建的表中。
3. 数据分栏
数据分栏常用于数据展现,将有相似属性的数据分栏列出来,可以互相比较查看。
【例 3】 分栏列出销售部和研发部工资超 1 万的员工名称及工资(每栏按从多到少排序)。员工表部分数据如下:
ID |
NAME |
SURNAME |
STATE |
DEPT |
SALARY |
1 |
Rebecca |
Moore |
California |
R&D |
7000 |
2 |
Ashley |
Wilson |
New York |
Finance |
11000 |
3 |
Rachel |
Johnson |
New Mexico |
Sales |
9000 |
4 |
Emily |
Smith |
Texas |
HR |
7000 |
5 |
Ashley |
Smith |
Texas |
R&D |
16000 |
… |
… |
… |
… |
… |
… |
期望结果如下:
SALESNAME |
SALARY |
RDNAME |
SALARY |
Madeline |
15000 |
Ashley |
16000 |
Jacob |
12000 |
Jacob |
16000 |
Andrew |
12000 |
Ryan |
13000 |
… |
… |
… |
… |
SPL 处理数据分栏,与之前的方法类似。还是先构造目标数据结构,再填入数据。
SPL 脚本如下:
A |
|
1 |
=T("Employee.csv").select(SALARY >10000).sort@z(SALARY) |
2 |
=A1.select(DEPT:"Sales") |
3 |
=A1.select(DEPT:"R&D") |
4 |
=create('SALESNAME',SALARY,'RDNAME', SALARY) |
5 |
=A4.paste(A2.(NAME),A2.(SALARY),A3.(NAME),A3.(SALARY)) |
A1:导入员工表,选出工资超过 1 万的记录,并按工资降序排列。
A2:取出销售部数据。
A3:取出研发部数据。
A4:按目标结构创建一个空表。
A5:使用函数 A.paste() 将值粘贴到对应列。
英文版