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

【摘要】
    在分组时经常会要求结果集必须按基准集合的次序出现,这种对齐分组在日常统计中是很常见的。我们还能把对齐分组推广成更一般的枚举分组。如何简便快捷的处理对齐分组,这里为你全程解析,并提供 esProc 示例代码。按指定基准对齐的分组运算

 

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

1.     普通对齐分组

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

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

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

..

【SPL 脚本】

 AB
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的执行结果如下:

IDNAMETeacherID
1Environmental   protection and sustainable development5
10Music   appreciation18

 

1.2    每组保留所有匹配成员

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

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

..

【SPL 脚本】

 AB
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的执行结果如下:

DEPTCOUNT
Admin4
R&D29
Sales187

 

1.3    不匹配记录放到新组

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

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

IDNAMESTATESALARY
1RebeccaCalifornia7000
2AshleyNew   York11000
3RachelNew   Mexico9000
4EmilyTexas7000
5AshleyTexas16000

【SPL 脚本】

 AB
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的执行结果如下:

STATESALARY
California7700.0
Texas7592.59
New   York7677.77
Florida7145.16
Other7308.1

 

2.     序号对齐分组

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

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

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

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

..

【SPL 脚本】

 AB
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的执行结果如下:

IDNameState
ALFKICMA-CGMTexas
CENTCNedlloydFlorida

 

2.2    每组保留所有匹配成员

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

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

 

IDCustomerIDOrderDateAmount
10248VINET2012/07/04428.0
10249TOMSP2012/07/051842.0
10250HANAR2012/07/081523.5
10251VICTE2012/07/08624.95
10252SUPRD2012/07/093559.5

【SPL 脚本】

 AB
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的执行结果如下:

MonthOrderCount
133
229
330
431
532
630
733
833
937
1038
1134
1248

 

2.3    按序号重复性分组

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

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

 

IDTitleAuthorLabel
1Easy   analysis of Excel2Excel,ETL,Import,Export
2Early   commute: Easy to pivot excel3Excel,Pivot,Python
3Initial   experience of SPL1Basics,Introduction
4Talking   about set and reference4Set,Reference,Dispersed,SQL
5Early   commute: Better weapon than Python4Python,Contrast,Install

【SPL 脚本】

 AB
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的执行结果如下:

LabelCount
SPL7
SQL6
Basics5

 

2.4    分段分组

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

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

 

IDNAMEBIRTHDAYSALARY
1Rebecca1974-11-207000
2Ashley1980-07-1911000
3Rachel1970-12-179000
4Emily1985-03-077000
5Ashley1975-05-1316000

【SPL 脚本】

 AB
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的执行结果如下:

SALARYCOUNT
0308
8000153
1200039

 

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

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

IDNAMEBIRTHDAYSALARY
1Rebecca1974-11-207000
2Ashley1980-07-1911000
3Rachel1970-12-179000
4Emily1985-03-077000
5Ashley1975-05-1316000

【SPL 脚本】

 AB
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的执行结果如下:

EntryYearsAvgSalary
06777.78
107445.53
206928.57

 

3.     枚举分组

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

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

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

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

 

IDCityPopulationProvince
1Shanghai12286274Shanghai
2Beijing9931140Beijing
3Chongqing7421420Chongqing
4Guangzhou7240465Guangdong
5Hong   Kong7010000Hong   Kong Special Administrative Region

【SPL 脚本】

 AB
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 岁] 将员工分组,统计平均工资,不满足条件的分到新组。员工薪资表部分数据如下:

IDNAMEBIRTHDAYSALARY
1Rebecca1974-11-207000
2Ashley1980-07-1911000
3Rachel1970-12-179000
4Emily1985-03-077000
5Ashley1975-05-1316000

【SPL 脚本】

 AB
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的执行结果如下:

AGEAvgSalary
?<357118.18
?<457448.16
Other7395.06

 

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

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

【例 11】 根据城市 GDP 表,分别统计直辖市、一线城市、二线城市的人均 GDP,分组时可能重复。城市 GDP 表部分数据如下:

 

IDCityGDPPopulation
1Shanghai326792418
2Beijing303202171
3Shenzhen246911253
4Guangzhou230001450
5Chongqing203633372

【SPL 脚本】

 AB
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的执行结果如下:

AreaCapitaGDP
["Beijing","Shanghai","Tianjing","Chongqing"].pos(?)>0107345.03
["Beijing","Shanghai","Guangzhou","Shenzhen"].pos(?)>0151796.49
["Chengdu","Hangzhou","Chongqing","Wuhan","Xian","Suzhou","Tianjing","Nanjing","Changsha","Zhengzhou","Dongguan","Qingdao","Shenyang","Ningbo","Kunming"].pos(?)>0106040.57

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值