SPL:按指定基准对齐的分组和排序
在分组时经常会要求结果集必须按基准集合的次序出现,这种对齐分组在日常统计中是很常见的。比如按北上广深的顺序,统计某公司在这些城市的总销售额;按指定的部门顺序,查询各部门的平均工资等等。
这种分组我们称为对齐分组。对齐分组可能会有空组,也可能有成员未分配到任何一个组中。
1. 按指定基准集合排序
按基准表中指定字段的顺序,将数据排序,每组保留最多一个匹配成员。适用于我们希望按照指定顺序查看或者使用数据的情况。
【例 1】 根据某年的中国城市 GDP 表,按照北上广深的顺序查询这些一线城市的 GDP 和人口。部分数据如下:
ID | CITY | GDP | POPULATION |
1 | Shanghai | 32679 | 2418 |
2 | Beijing | 30320 | 2171 |
3 | Shenzhen | 24691 | 1253 |
4 | Guangzhou | 23000 | 1450 |
5 | Chongqing | 20363 | 3372 |
… | … | … | … |
在 SPL 中函数 A.align() 用于对齐分组,默认每组保留最多一个匹配成员。
SPL脚本如下:
A | |
1 | =T("CityGDP.txt") |
2 | ["Beijing","Shanghai","Guangzhou","Shenzhen"] |
3 | =A1.align(A2,CITY) |
4 | =A3.new(CITY,GDP,POPULATION) |
A1:查询城市 GDP 表。
A2:定义城市序列。
A3:使用函数 A.align(),将城市 GDP 表按照指定的城市序列排序,每组保留最多一个匹配成员。
A4:创建以城市、GDP、人口为字段的结果表。
其中A4的执行结果如下:
CITY | GDP | POPULATION |
Beijing | 30320 | 2171 |
Shanghai | 32679 | 2418 |
Guangzhou | 23000 | 1450 |
Shenzhen | 24691 | 1253 |
2. 每组保留所有匹配成员
按基准表中指定字段的顺序,将数据分组,每组保留所有匹配成员。适用于关心每组的成员信息,或者需要用这些成员记录继续进行统计的场景。
【例 2】 根据相互关联的员工表和部门表,按部门表中的部门顺序统计各部门人数。员工表和部门表的关系如下:
在 SPL 中函数 A.align() 的选项 @a,用于在对齐分组时每组保留所有匹配成员。
SPL脚本如下:
A | |
1 | =connect("db") |
2 | =A1.query("select * from EMPLOYEE") |
3 | =A1.query("select * from DEPARTMENT") |
4 | =A2.align@a(A3:DEPT, DEPT) |
5 | =A3.new(DEPT, A4(#).count():COUNT) |
A1:连接数据库。
A2:查询员工表。
A3:查询部门表。
A4:使用函数 A.align@a() 将员工按部门对齐分组,其中选项 @a 每组返回所有匹配成员。
A5:根据部门表创建结果序列,并通过 A4 对齐分组后的结果计算每组的数量,即每个部门的人数。
其中A5的执行结果如下:
DEPT | COUNT |
Administration | 4 |
Finance | 24 |
HR | 19 |
… | … |
对齐分组可能会有空组,也就是没有一个成员被分配到某个分组中。
【例 3】 根据相互关联的课程表和选课表,按课程表顺序查询各课程报名的人数。课程表与选课表的关系如下:
SPL脚本如下:
A | |
1 | =connect("db") |
2 | =A1.query("select * from SELECT_COURSE") |
3 | =A1.query("select * from COURSE") |
4 | =A2.align@a(A3:ID,COURSEID) |
5 | =A3.new(ID, A4(#).len():COUNT) |
A1:连接数据库。
A2:查询选课表。
A3:查询课程表。
A4:使用函数 A.align@a(),将选课表按照课程表的 ID 对齐,每组保留所有匹配成员。
对齐分组后的结果中可能会有空组,也就是有的课程没有学生选择:
成员 |
[] |
[[13,2,7],[15,2,50],…] |
[[7,3,41],[11,3,5],…] |
[[45,4,28],[51,4,18],…] |
[[3,5,52],[4,5,44],…] |
… |
A5:根据课程表创建结果序列,并通过 A4 对齐分组后的结果计算每组的数量,即选择该课程的人数。
其中A5的执行结果如下:
ID | COUNT |
1 | 0 |
2 | 6 |
3 | 5 |
4 | 4 |
5 | 11 |
… | … |
3. 不匹配记录放到新组
按基准表中指定字段的顺序,将数据分组,不匹配的记录放到新组。适用于不仅关心匹配的成员信息,还要关心其他不匹配记录的场景。
【例 4】 根据员工表,统计 [California, Texas, New York, Florida] 的平均工资,其他州作为“Other”组进行统计。员工表部分数据如下:
ID | NAME | STATE | DEPT | SALARY |
1 | Rebecca | California | R&D | 7000 |
2 | Ashley | New York | Finance | 11000 |
3 | Rachel | New Mexico | Sales | 9000 |
4 | Emily | Texas | HR | 7000 |
5 | Ashley | Texas | R&D | 16000 |
… | … | … | … | … |
在 SPL 中函数 A.align() 的选项 @n,用于在对齐分组时将不匹配记录放到新组。
SPL脚本如下:
A | |
1 | =T("Employee.csv") |
2 | [California,Texas,New York,Florida] |
3 | =A1.align@an(A2,STATE) |
4 | =A3.new(if (#>A2.len(),"Other",STATE):STATE,~.avg(SALARY):AvgSalary) |
A1:查询员工表。
A2:创建地区序列。
A3:使用函数 A.align@an() 将员工表按地区对位分组,选项 @a 每组返回所有匹配成员,选项 @n 不匹配成员存放到新组。
A4:统计每组的平均工资,将不匹配的分组(最后一组)命名为“Other”。
其中A4的执行结果如下:
STATE | AvgSalary |
California | 7700.0 |
Texas | 7592.59 |
New York | 7677.77 |
Florida | 7145.16 |
Other | 7308.1 |