按指定基准对齐的分组运算

梦想的初衷 提交于 2020-11-08 13:01:16

对照一个基准集合,将待分组集合成员的某个字段或表达式与基准集合成员比较,相同者则分到同一个组中,最后拆分出来的组数和基准集合成员数是相同的。这种分组我们称为对齐分组。对齐分组可能会有空组,也可能有成员未分配到任何一个组中。

1.     普通对齐分组

1.1    每组保留最多一个匹配成员

按某字段的指定顺序,将表中所有记录分组并汇总求和。

【例 1】 根据相互关联的课程表和选课表,按课程表顺序查询有哪些课程无人选择:

..

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   SelectCouse") /查询选课表
3 =A1.query("select * from Course") /查询课程表
4 =A2.align(A3:ID,CourseID) /使用函数 A.align(),将选课表按照课程表的 ID 对齐,每组选择一个匹配成员
5 =A3(A4.pos@a(null)) /在课程表中选出没有选择(值为 null)的课程信息

    A5的执行结果如下:

ID NAME TeacherID
1 Environmental   protection and sustainable development 5
10 Music   appreciation 18

 

1.2    每组保留所有匹配成员

按某字段的指定顺序,将表中所有记录分组并汇总求和。

【例 2】 根据相互关联的员工表和部门表,按部门表中的部门顺序统计各部门人数:

..

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   EMPLOYEE") /查询员工表
3 =A1.query("select * from   DEPARTMENT") /查询部门表
4 =A2.align@a(A3:ID, DEPARTMENT) /使用函数 A.align@a(),将员工表按部门对齐分组,@a 选项每组返回所有匹配成员
5 =A4.new(DEPT, ~.count():COUNT) /统计各部门的人数

    A5的执行结果如下:

DEPT COUNT
Admin 4
R&D 29
Sales 187

 

1.3    不匹配记录放到新组

按某字段的指定顺序,将表中所有记录分组,不匹配记录放到新组。

【例 3】 根据员工薪资表,统计 [California, Texas, New York, Florida] 的平均工资,未指定的州作为“Other”统计。员工薪资表部分数据如下:

ID NAME STATE SALARY
1 Rebecca California 7000
2 Ashley New   York 11000
3 Rachel New   Mexico 9000
4 Emily Texas 7000
5 Ashley Texas 16000

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   EMPLOYEE") /查询雇员表
3 [California,Texas,New York,Florida] /创建地区序列
4 =A2.align@an(A3,STATE) /使用函数 A.align@an(),将雇员表按地区对位分组,@a 选项每组返回所有匹配成员,@n 选项不匹配成员存放到新组。
5 =A4.new(if (#>A3.len(),"Other",STATE):STATE,~.avg(SALARY):AvgSalary) /统计每组的平均工资,产生新序表。最后一组的地区更名为 Other,否则为当前组第一条记录的地区。

    A5的执行结果如下:

STATE SALARY
California 7700.0
Texas 7592.59
New   York 7677.77
Florida 7145.16
Other 7308.1

 

2.     序号对齐分组

序号对齐分组,是指按照指定的序号进行分组,序号相同的成员分到同一组。

2.1    每组保留最多一个匹配成员

在相互关联的两个表中,查找未被引用的记录。

【例 4】 根据相互关联的销售表和客户表,顺序列出 2014 年没有销售记录的客户:

..

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from Sales") /查询销售表
3 =A1.query("select * from   Customer") /查询客户表
4 =A3.(ID) /从客户表中选出客户序号
5 =A2.align(A4.len(), A4.pos(CustomerID)) /使用函数 A.align(n,y),将销售表按照客户序号对位分组
6 =A3(A5.pos@a(null)) /在客户表中选出没有销售记录(值为 null)的客户信息

A6的执行结果如下:

ID Name State
ALFKI CMA-CGM Texas
CENTC Nedlloyd Florida

 

2.2    每组保留所有匹配成员

按序号将表中所有记录分组并汇总求和。

【例 5】 根据订单表,顺序列出 2013 年每月的订单总数。订单表部分数据如下:

 

ID CustomerID OrderDate Amount
10248 VINET 2012/07/04 428.0
10249 TOMSP 2012/07/05 1842.0
10250 HANAR 2012/07/08 1523.5
10251 VICTE 2012/07/08 624.95
10252 SUPRD 2012/07/09 3559.5

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from Orders where   year(OrderDate)=2013") /查询 2013 年的订单
3 =A2.align@a(12,month(OrderDate)) /使用函数 A.align@a(),将订单表按月份对位分为 12 组,@a 选项每组选择所有匹配成员
4 =A3.new(#:Month,~.count():OrderCount) /列出每月的订单总数

A4的执行结果如下:

Month OrderCount
1 33
2 29
3 30
4 31
5 32
6 30
7 33
8 33
9 37
10 38
11 34
12 48

 

2.3    按序号重复性分组

按计算出的序号数列重复性分组并计算。

【例 6】 根据发帖记录表,按标签将帖子分组,并统计各个标签出现频数。发帖记录表部分数据如下:

 

ID Title Author Label
1 Easy   analysis of Excel 2 Excel,ETL,Import,Export
2 Early   commute: Easy to pivot excel 3 Excel,Pivot,Python
3 Initial   experience of SPL 1 Basics,Introduction
4 Talking   about set and reference 4 Set,Reference,Dispersed,SQL
5 Early   commute: Better weapon than Python 4 Python,Contrast,Install

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   PostRecord") /查询发帖记录表
3 =A2.conj(Label.split(",")).id() /将标签按逗号分隔后合并到一个序列,获得没有重复值的全部标签。
4 =A2.align@ar(A3.len(),A3.pos(Label.split(","))) /使用 align 函数的 @r 选项,按照每个帖子的标签在全部标签中的定位分组。
5 =A4.new(A3(#):Label,~.count():Count).sort@z(Count) /统计每个标签的帖子数量,按降序排列

A5的执行结果如下:

Label Count
SPL 7
SQL 6
Basics 5

 

2.4    分段分组

根据指定字段的值,分段分组并汇总计数。

【例 7】 根据员工薪资表,按工资 8000 以下、8000~12000 和 12000 以上分组,并统计各组的人数。员工薪资表部分数据如下:

 

ID NAME BIRTHDAY SALARY
1 Rebecca 1974-11-20 7000
2 Ashley 1980-07-19 11000
3 Rachel 1970-12-17 9000
4 Emily 1985-03-07 7000
5 Ashley 1975-05-13 16000

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   EMPLOYEE") /查询员工表
3 [0,8000,12000] /定义工资区间
4 =A2.align@a(A3.len(),A3.pseg(SALARY)) /使用函数 A.pseg(x) 获取工资所在区间
5 =A4.new(A3 (#):SALARY,~.count():COUNT) /统计每组的人数

A5的执行结果如下:

SALARY COUNT
0 308
8000 153
12000 39

 

根据表达式的计算结果,将记录分段分组并汇总计算平均值。

【例 8】根据员工表,按入职时间 10 年以下,10~20 年和 20 年以上分组,并统计每组的平均工资。员工表部分数据如下:

ID NAME BIRTHDAY SALARY
1 Rebecca 1974-11-20 7000
2 Ashley 1980-07-19 11000
3 Rachel 1970-12-17 9000
4 Emily 1985-03-07 7000
5 Ashley 1975-05-13 16000

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   EMPLOYEE") /查询员工表
3 [0,10,20] /定义入职年限区间
4 =now() /获取当前日期时间
5 =A2.align@a(A3.len(),A3.pseg(elapse@y(A4,-~),   HIREDATE)) /使用函数 A.pseg(x,y) 获取入职时间所在区间
6 =A5.new(A3(#):EntryYears,~.avg(SALARY):AvgSalary) /统计每组的平均工资

A6的执行结果如下:

EntryYears AvgSalary
0 6777.78
10 7445.53
20 6928.57

 

3.     枚举分组

枚举分组是指,事先指定一组枚举条件,将待分组集合的成员作为参数计算这批条件,条件成立者都被划分到与该条件对应的一个子集中,结果集的子集和事先指定的条件一一对应。

3.1    每个成员只存放到第一个匹配组

根据枚举条件表达式,将记录分组,分组时记录只置于第一个匹配组。

【例 9】 根据中国主要城市人口表,按人口将城市分类。中国主要城市人口表部分数据如下:

 

ID City Population Province
1 Shanghai 12286274 Shanghai
2 Beijing 9931140 Beijing
3 Chongqing 7421420 Chongqing
4 Guangzhou 7240465 Guangdong
5 Hong   Kong 7010000 Hong   Kong Special Administrative Region

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   UrbanPopulation") /查询城市人口表
3 [?>2000000,?>1000000,?>500000,?<=500000] /超大城市 200 万人口以上,特大城市 100-200 万人口,大城市 50-100 万,其他中小城市。
4 =A2.enum(A3,Population) /使用函数 A.enum(),将人口按 A3 定义的条件进行枚举分组

A4的执行结果如下:

..

3.2    不匹配成员存放到新组

根据枚举条件表达式,将记录分组,不匹配记录放到新组。

【例 10】 根据员工薪资表,按年龄条件 [小于 35 岁, 小于 45 岁] 将员工分组,统计平均工资,不满足条件的分到新组。员工薪资表部分数据如下:

ID NAME BIRTHDAY SALARY
1 Rebecca 1974-11-20 7000
2 Ashley 1980-07-19 11000
3 Rachel 1970-12-17 9000
4 Emily 1985-03-07 7000
5 Ashley 1975-05-13 16000

【SPL 脚本】


A B
1 =connect("db") /连接数据库
2 =A1.query("select * from   EMPLOYEE") /查询员工表
3 [?<35,?<45] /将年龄段划分为 35 岁以下,45 岁以下
4 =A2.enum@n(A3, age(BIRTHDAY)) /使用函数 A.enum@n(),按年龄枚举分组,选项 @n 不匹配成员存放到新组。
5 =A4.new(if (#>A3.len(),   "Other",A3(#)):AGE,~.avg(SALARY):AvgSalary) /统计每组的平均工资,最后一组名称设置为 Other

A5的执行结果如下:

AGE AvgSalary
?<35 7118.18
?<45 7448.16
Other 7395.06

 

3.3    按照枚举条件可重复分组

根据不同的指定序列,将记录分组并计算,分组时记录可重复。

【例 11】 根据城市 GDP 表,分别统计直辖市、一线城市、二线城市的人均 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 B
1 =connect("db") /连接数据库
2 =A1.query("select * from GDP") /查询城市 GDP 表
3 [["Beijing","Shanghai","Tianjing","Chongqing"].pos(?)>0,["Beijing","Shanghai","Guangzhou","Shenzhen"].pos(?)>0,["Chengdu","Hangzhou","Chongqing","Wuhan","Xian","Suzhou","Tianjing","Nanjing","Changsha","Zhengzhou","Dongguan","Qingdao","Shenyang","Ningbo","Kunming"].pos(?)>0] /枚举直辖市、一线城市和二线城市
4 =A2.enum@r(A3,City) /使用函数 A.enum@r(),按城市枚举分组。选项 @r 表示可重复分组。
5 =A4.new(A3(#):Area,~.sum(GDP)/~.sum(Population)*10000:CapitaGDP) /统计每组的人均 GDP

A5的执行结果如下:

Area CapitaGDP
["Beijing","Shanghai","Tianjing","Chongqing"].pos(?)>0 107345.03
["Beijing","Shanghai","Guangzhou","Shenzhen"].pos(?)>0 151796.49
["Chengdu","Hangzhou","Chongqing","Wuhan","Xian","Suzhou","Tianjing","Nanjing","Changsha","Zhengzhou","Dongguan","Qingdao","Shenyang","Ningbo","Kunming"].pos(?)>0 106040.57

 《SPL CookBook》中还有更多相关计算示例。


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!