SPL:取最大值 / 组内最大值所在记录
有些时候,我们并不关心最大值具体是多少,而是关心最大值所在记录。比如查询数学成绩最高的学生 ID, 选出每个月销售额最高的订单信息等等。
1. 取最大值所在记录
取最大值所在记录,需要找到最大值出现在哪些行上(有多个最大值时可能是多行),再返回对应的记录。SPL 提供了函数 A.maxp() 用于选出最大值所在记录。
【例 1】 根据成绩表,求一班数学成绩最高的学生 ID。部分数据如下:
CLASS |
STUDENTID |
SUBJECT |
SCORE |
1 |
1 |
English |
84 |
1 |
1 |
Math |
77 |
1 |
1 |
PE |
69 |
1 |
2 |
English |
81 |
1 |
2 |
Math |
80 |
… |
… |
… |
… |
SPL 脚本如下:
A |
|
1 |
=T("Scores.csv").select(SUBJECT=="Math"&&CLASS==1) |
2 |
=A1.maxp(SCORE).STUDENTID |
A1:导入成绩表,并查询一班的数学成绩。
A2:使用了函数 A.maxp() 选出最高分所在的记录,再从记录中取学生 ID。
最大值所在记录不一定是唯一的,如果想返回所有最高分记录,可以使用函数A.maxp()的选项@a :
A |
|
2 |
=A1.maxp@a(SCORE).(STUDENTID) |
A2:使用 A.maxp() 函数的 @a 选项,选出所有最高分的记录,然后取出所有学生 ID。
其中 A1.maxp@a(SCORE) 的执行结果如下:
CLASS |
STUDENTID |
SUBJECT |
SCORE |
1 |
10 |
Math |
97 |
1 |
13 |
Math |
97 |
可以看到一班的数学最高分有两位同学,他们的学号分别是 10 和 13。
类似的,SPL 也提供了函数 A.minp(),用于取最小值所在记录。如果想取所有最小值所在记录,函数 A.minp() 也支持选项 @a。
2. 取组内最大值所在记录
通常人们对分组后的聚合值更感兴趣,因此分组运算常常伴随着对子集的进一步汇总计算。通过分组汇总,我们可以很方便的计算每组的最大值或最小值。但是,我们仍然有对这些分组子集而不是聚合值更感兴趣的时候。比如说,我们想要知道每个月单笔销售额最高的销售记录中,客户名称、销售人员等信息,而不在意最高的销售额具体是多少。
SPL提供了函数 group(),我们可以用它来实现真正的分组,分组后的结果集是由多个分组子集组成的集合。这就使得 group 函数可以支持,在每个分组子集中取最大值所在记录这样的运算。我们通过一个简单的例子来看一下,如何取组内最大值所在记录。
【例 2】 根据销售表,取出 2014 年每个月销售额最高的销售记录。部分数据如下:
ID |
CUSTOMERID |
ORDERDATE |
SELLERID |
AMOUNT |
10400 |
EASTC |
2014/01/01 |
1 |
3063.0 |
10401 |
HANAR |
2014/01/01 |
1 |
3868.6 |
10402 |
ERNSH |
2014/01/02 |
8 |
2713.5 |
10403 |
ERNSH |
2014/01/03 |
4 |
1005.9 |
10404 |
MAGAA |
2014/01/03 |
2 |
1675.0 |
… |
… |
… |
… |
… |
我们首先选出 2014 年的销售记录,将销售记录按照月份进行分组,并从每个月份的销售记录中选出销售额最大的记录,最后将这些选出的记录合并在一起。
SPL脚本如下:
A |
|
1 |
=T("Sales.csv").select(year(ORDERDATE)==2014) |
2 |
=A1.group(month(ORDERDATE);~.maxp@a(AMOUNT):MAX_AMOUNT) |
3 |
=A2.conj(MAX_AMOUNT) |
A1:导入销售表,并选出 2014 年的销售数据。
A2:使用函数 A.group() 将销售记录按照月份进行分组,并选出每个分组子集中销售额最大的记录。
A3:将所有月份的最大值记录合并。