SPL:获取分组子集后再统计

   把集合中具有相同属性的成员分配到同一个组,这就是分组运算。比如员工表根据部门分组,每组的员工都具有相同的部门;销售表可以根据销售年份分组,每组都是同一个年份的销售记录等等。

   分组运算的实质是将一个集合按照某种规则拆分成若干个子集,也就是说,返回值应当是一个由集合构成的集合。对于每个成员集合,我们称为分组子集。

   通常人们对分组子集的聚合值更感兴趣,因此分组运算常常伴随着对子集的进一步汇总计算。但是,我们仍然有对这些分组子集而不是聚合值更感兴趣的时候。

    我们以员工表为例,部分数据如下:

ID

NAME

BIRTHDAY

STATE

DEPT

SALARY

1

Rebecca

1974/11/20

California

R&D

7000

2

Ashley

1980/07/19

New   York

Finance

11000

3

Rachel

1970/12/17

New   Mexico

Sales

9000

4

Emily

1985/03/07

Texas

HR

7000

5

Ashley

1975/05/13

Texas

R&D

16000

 

【例 1】找出有相同出生日期的员工。

   在 SPL 中提供了函数 A.group(),我们可以用它来实现真正的分组,分组后的结果集是由多个分组子集组成的集合。

SPL 脚本如下:


A

1

=T("Employee.csv")

2

=A1.group(BIRTHDAY)

3

=A2.select(~.len()>1).conj()

A1:导入员工表。

A2:使用了函数 A.group() 按出生日期分组。

A3:选择成员数量大于 1 的分组,即有相同出生日期的子集。再将这些子集合并。

 

    严格来说,分组和汇总是两个独立的动作,但在 SQL 中总是一起出现,从而给人一种两者必须同时使用的假象。事实上,这种组合是对分组操作的一种局限,或者说分组之后,能够进行的计算远不止 SQL 中的几种聚合函数。

 

【例 2】查询年龄低于部门平均年龄的员工。

   前面已经介绍过,在 SPL 中函数 A.group()用于分组。我们可以在函数 A.group() 中,定义在分组后对每个分组子集的运算。不限于 SUM、COUNT 等聚合运算,可以定义一些复杂运算。

SPL脚本如下:


A

1

=T("Employee.csv")

2

=A1.group(DEPT; (a=~.avg(age(BIRTHDAY)), ~.select(age(BIRTHDAY)<a)):YOUNG)

3

=A2.conj(YOUNG)

A1:导入员工表。

A2:按部门分组,并在每个分组中选出年龄低于平均年龄的记录。在函数 A.group() 的聚合运算中,我们可以使用临时变量,使得运算更加简单易懂。

A3:将选出的记录合并。

 

【例 3】选出员工人数超过 50 人的州,查询这些州各部门的平均工资。

   分组本身是复杂运算,保留分组子集可重复使用,提高运行效率。在 SPL 中,函数 A.group() 在分组后可以保留分组子集,可以针对分组子集再次进行分组汇总等运算。

SPL脚本如下:


A

1

=T("Employee.csv")

2

=A1.group(STATE).select(~.len()>50)

3

=A2.conj(~.groups(DEPT; avg(SALARY):AVG_SALARY).derive(A2.~.STATE:STATE))

A1:导入员工表。

A2:按州进行分组,并选出员工数大于 50 人的分组子集。

A3:对每个州的分组子集再按部门分组汇总平均工资,再把这些结果集合并。

Employee.csv