非常规聚合问题举例
【摘要】
聚合运算是指对数据进行计算,返回聚合结果。聚合运算经常伴随着分组运算,除了常见的求和、最大值、最小值、计数等聚合运算,还有一些逻辑运算等等。如何简便快捷的处理聚合问题,这里为你全程解析,并提供 esProc 示例代码。非常规聚合问题举例
1. 枚举分组后聚合求和
【例 1】 从城市 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) |
/按城市枚举分组 |
5 |
=A4.new(A3(#):Area,~.sum(GDP)/~.sum(Population)*10000:CapitaGDP) |
/统计每组的人均 GDP。其中用到了函数 sum() 求和 |
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 |
2. 合并重叠的时间区间
【例 2】 将客户 ANATR 有重复时间段的订单记录合并。客户表部分数据如下:
OrderID |
Customer |
SellerId |
OrderDate |
FinishDate |
10308 |
ANATR |
7 |
2012/09/18 |
2012/10/16 |
10309 |
ANATR |
3 |
2012/09/19 |
2012/10/17 |
10625 |
ANATR |
3 |
2013/08/08 |
2013/09/05 |
10702 |
ANATR |
1 |
2013/10/13 |
2013/11/24 |
10759 |
ANATR |
3 |
2013/11/28 |
2013/12/26 |
… |
… |
… |
… |
… |
【SPL脚本】
A |
B |
|
1 |
=connect("db") |
/连接数据源 |
2 |
=A1.query("select * from Orders where Customer='ANATR'order by OrderDate") |
/选出客户 ANATR 的订单信息,按订单日期排序 |
3 |
=A2.group@i(OrderDate>max(FinishDate[,-1])) |
/当订单日期大于前面所有订单的完成日期时分到新组 |
4 |
=A3.new(Customer,~.min(OrderDate):OrderDate,~.max(FinishDate):FinishDate) |
/使用函数 min() 计算每组最早的订单日期作为订单日期,使用函数 max 计算最晚的订单日期作为完成日期 |
A4的执行结果如下:
Customer |
OrderDate |
FinishDate |
ANATR |
2012/09/18 |
2012/10/17 |
ANATR |
2013/08/08 |
2013/09/05 |
ANATR |
2013/10/13 |
2013/11/24 |
ANATR |
2013/11/28 |
2013/12/29 |
… |
… |
… |
3. 在分组聚合中统计满足条件的数量
【例 4】 求一班各科不及格人数。成绩表部分数据如下:
CLASS |
STUDENTID |
SUBJECT |
SCORE |
Class one |
1 |
English |
84 |
Class one |
1 |
Math |
77 |
Class one |
1 |
PE |
69 |
Class one |
2 |
English |
81 |
Class one |
2 |
Math |
80 |
… |
… |
… |
… |
【SPL 脚本】
A |
B |
|
1 |
=connect("db") |
/连接数据库 |
2 |
=A1.query("select * from Scores where CLASS='Class one'") |
/查询一班学生成绩 |
3 |
=A2.groups(SUBJECT; count(SCORE<60):FailCount) |
/分组汇总,其中用到了函数 count() 统计不及格人数 |
A3的执行结果如下:
SUBJECT |
FailCount |
English |
2 |
Math |
0 |
PE |
2 |
4. 在布尔值构成的集合中,聚合时执行逻辑与运算
【例 5】 根据一系列某小学在线教学终端调查表,查看是否所有学生都能够使用手机。各班问卷及汇总目录如下:
ID |
STUDENT_NAME |
TERMINAL |
1 |
Rebecca Moore |
Phone |
2 |
Ashley Wilson |
Phone,PC,Pad |
3 |
Rachel Johnson |
Phone,PC,Pad |
4 |
Emily Smith |
Phone,Pad |
5 |
Ashley Smith |
Phone,PC |
6 |
Matthew Johnson |
Phone |
7 |
Alexis Smith |
Phone,PC |
8 |
Megan Wilson |
Phone,PC,Pad |
… |
… |
… |
【SPL 脚本】
A |
B |
C |
|
1 |
=directory@ps("D:/Primary School") |
/递归遍历目录,列出所有文件 |
|
2 |
for A1 |
=file(A2).xlsimport@t() |
/循环导入各班级问卷 excel 文件 |
3 |
=B2.([TERMINAL,"Phone"].ifn().split@c().pos("Phone") > 0)|@ |
/当问卷中终端未填写时不认为不支持手机终端,使用函数 ifn() 保证此项为 true。 |
|
4 |
=B3.cand() |
/使用函数 A.cand() 计算 B3 的成员是否都是 true |
A4的执行结果如下:
Value |
false |
5. 在布尔值构成的集合中,聚合时执行逻辑或运算
【例 6】 查询客户 RATTC,在 2014 年是否排进过单月销售额的前三名。销售表部分数据如下:
OrderID |
Customer |
SellerId |
OrderDate |
Amount |
10400 |
EASTC |
1 |
2014/01/01 |
3063.0 |
10401 |
HANAR |
1 |
2014/01/01 |
3868.6 |
10402 |
ERNSH |
8 |
2014/01/02 |
2713.5 |
10403 |
ERNSH |
4 |
2014/01/03 |
1005.9 |
10404 |
MAGAA |
2 |
2014/01/03 |
1675.0 |
… |
… |
… |
… |
… |
【SPL脚本】
A |
B |
|
1 |
=connect("db").query("select * from sales") |
/连接数据源,读取销售表 |
2 |
=A1.select(year(OrderDate)==2014) |
/选出 2014 年数据 |
3 |
=A2.group(month(OrderDate)) |
/将 2014 年的数据按照月份分组 |
4 |
=A3.(~.groups(Customer; sum(Amount):Amount)) |
/分组后的成员按照客户分组汇总销售额 |
5 |
=A4.new(~.top(-3; Amount):Top3) |
/循环每个月的数据,计算每月销售额前 3 的客户 |
6 |
=A5.(Top3.(Customer).pos("RATTC")>0) |
/判断每个月前三名是否包含客户 RATTC |
7 |
=A6.cor() |
/使用函数 A.cor() 计算 A6 的成员是否存在 true |
A7的执行结果如下:
Value |
false |
《SPL CookBook》中还有更多相关计算示例。