结构化数据上的选出运算

【摘要】
    选出是指在集合中,根据指定条件获取成员。选出与定位计算很相似,不过定位关心的是成员在集合中的位置,而选出关心的是成员记录的详细信息。比如选出入职超过 10 年的员工收入,查询销售额超过一万的客户名称等等。如何简单快捷的实现选出?这里将为你全程剖析,并提供 esProc SPL 示例代码。 结构化数据上的选出运算

1. 选出符合条件的成员

【例 1】 分栏列出欧洲和非洲人口超 200 万的城市名称及人口(每栏按从多到少排序)。世界城市人口表部分数据如下:

Continent

Country

City

Population

Africa

Egypt

Cairo

6789479

Asia

China

Shanghai

24240000

Europe

Britain

London

7285000

…

…

…

…

期望结果如下:

Europe   City

Population

Africa   City

Population

Moscow

8389200

Cairo

6789479

London

7285000

Kinshasa

5064000

St   Petersburg

4694000

Alexandria

3328196

…

…

…

…

 

【SPL 脚本】


A

B

1

=connect("db").query("select   * from World where Continent in('Europe','Africa') and Population >=   2000000")

/连接数据库,取出欧洲和非洲超过 200 万人口的记录

2

=A1.select(Continent:"Europe")

/使用 A.select() 函数取出欧洲数据

3

=A1.select(Continent:"Africa")

/使用 A.select() 函数取出非洲数据

4

=create('Europe City',Population,'Africa   City', Population)

/按目标结构创建一个空表

5

=A4.paste(A2.(City),A2.(Population),A3.(City),A3.(Population))

/使用 A.paste() 函数将值粘贴到对应列

A4的执行结果如下:

Europe   City

Population

Africa   City

Population

Moscow

8389200

Cairo

6789479

London

7285000

Kinshasa

5064000

St   Petersburg

4694000

Alexandria

3328196

…

…

…

…

 

【例 2】 查询纽约研发部门员工的全名和收入。部分数据如下:

ID

NAME

SURNAME

STATE

DEPT

SALARY

1

Rebecca

Moore

California

R&D

7000

2

Ashley

Wilson

New   York

Finance

11000

3

Rachel

Johnson

New   Mexico

Sales

9000

4

Emily

Smith

Texas

HR

7000

5

Ashley

Smith

Texas

R&D

16000

…

…

…

…

…

…

 

【SPL 脚本】


A

B

1

=connect("db")

/连接数据源

2

=A1.query("select * from   Employee")

/导入员工表

3

=A2.select(STATE=="New York"&&DEPT=="R&D")

/使用函数 A.select() 选出纽约研发部门员工的记录。需要同时满足所有条件时,可以使用符号 "&&"。

4

=A3.new(NAME+" "+SURNAME:FULLNAME, SALARY)

/使用符号 + 连接字符串,组成全名

A4的执行结果如下:

FULLNAME

SALARY

Matthew   Johnson

6000

Lauren   Thomas

12000

Brooke   Williams

12000

 

【例 3】 查询各部门 30 岁以下和 50 岁以上的员工的人数。部分数据如下:

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

…

…

…

…

…

…

 

【SPL 脚本】


A

B

1

=connect("db")

/连接数据源

2

=A1.query("select * from   Employee")

/导入员工表

3

=A2.select((age=age(BIRTHDAY), age<30 ||   age>50))

/使用函数 A.select() 选出年龄小于 30 或者年龄大于 50 的员工。需要满足多个条件中任意一个时,可以使用符号 "||"。

4

=A3.groups(DEPT; count(~):Count)

/分组汇总各部门满足条件的人数

A4的执行结果如下:

DEPT

Count

4

9

5

5

6

3

7

6

8

1

 

2. 查找最大值 / 最小值对应记录

【例 4】 根据成绩表,求一班数学成绩最低的学生 ID。部分数据如下:

 

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   SUBJECT='Math'and CLASS='Class one'")

/查询一班的数学成绩

3

=A2.minp(SCORE)

/使用 A.minp() 函数选出最低分所在记录

4

=A3.STUDENTID

/从记录中取学生 ID

最小值所在记录不一定是唯一的,如果想返回所有记录,可以使用函数A.minp()的选项@a :


A

B

3

=A2.minp@a(SCORE)

/使用 A.minp() 函数的 @a 选项,选出所有最高分的记录

4

=A3.(STUDENTID)

/从多条记录中取出学生 ID

A3的执行结果如下:

CLASS

STUDENTID

SUBJECT

SCORE

Class   one

5

Math

60

Class   one

14

Math

60

A4的执行结果如下:

Member

5

14

 

【例 5】 根据奥运会奖牌榜统计表,求总成绩蝉联第一名届数最长的国家。部分数据如下:

Game

Nation

Gold

Silver

Copper

30

USA

46

29

29

30

China

38

27

23

30

UK

29

17

19

30

Russia

24

26

32

30

Korea

13

8

7

…

…

…

…

…

【SPL 脚本】


A

B

1

=file("Olympic.csv").import@cqt()

/导入奥运会历届排名

2

=A1.sort@z(Game, 1000000*Gold+1000*Silver+Copper)

/按第几届和总成绩降序排列

3

=A2.group@o1(Game)

/每届取一名,因为有序也就是第一名

4

=A3.group@o(Nation)

/将国家按原序分组

5

=A4.maxp(~.len())

/使用函数 A.maxp() 选出成员数量最多的一组,也就是蝉联次数最多的

A5的执行结果如下:

Game

Nation

Gold

Silver

Copper

10

USA

41

32

30

9

USA

22

18

16

8

USA

45

27

27

7

USA

41

27

28

 

3. 分区段查找数据

有时候我们需要通过计算数值在区间中的序号,来获取在集合中的对应成员。比如根据考试成绩返回评价(优、良、中、差);根据家庭年收入返回家庭所处的资产等级(贫困、小康、中产、富裕等)。

【例 6】 根据成绩表,统计英语科目优秀、及格和不及格的人数。部分数据如下:

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").query("select   * from Scores where SUBJECT='English'")

/连接数据库,查询英语成绩

2

=create(Assessment,Score).record(["fail",0,"pass",60,"excellent",90])

/创建分数与评价对照表

3

=A1.derive(A2.segp(Score,SCORE).Assessment:Assessment)

/使用 A.segp() 函数根据分数在对照表中的区间序号,获取相应的评价。

4

=A3.groups(Assessment;count(1):Count)

/按评价分组统计人数

A4的执行结果如下:

Assessment

Count

excellent

6

fail

4

pass

18

 

4. 选出前 N 名 / 后 N 名

【例 7】 根据成绩表,求各班各科前两名的学生 ID。部分数据如下:

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")

/查询学生成绩

3

=A2.group(CLASS,SUBJECT;~.top(-2;SCORE):TOP2)

/使用 A.top() 函数获取每个班级各科目分数的前两名。其中 -2 表示从大到小取两名。

4

=A3.conj(TOP2)

/将所有班级各科的前两名记录合并到一起

 

A4的执行结果如下:

CLASS

STUDENTID

SUBJECT

SCORE

Class   one

4

English

96

Class   one

9

English

93

Class   one

13

Math

97

Class   one

10

Math

97

…

…

…

…

 

5. 根据主键值查找对应记录

根据主键值查找对应记录是很常见的操作,例如根据员工 ID 查找员工记录,根据订单 ID 查询订单详细信息等等。

【例 8】 根据相互关联的课程表和选课表,列出所有学生所选课程信息表,每个科目作为一列。课程表部分数据如下:

ID

NAME

TEACHERID

1

Environmental   protection and …

5

2

Mental   health of College Students

1

3

Computer   language Matlab

8

…

…

…

    选课表部分数据如下:

ID

STUDENT_NAME

COURSE

1

Rebecca

2,7

2

Ashley

1,8

3

Rachel

2,7,10

…

…

…

    希望转换成如下表格:

ID

STUDENT_NAME

COURSE1

COURSE2

COURSE3

…

1

Rebecca

Mental   health of College Students

Into   Shakespeare


…

2

Ashley

Environmental   protection and …

Modern   economics


…

3

Rachel

Mental   health of College Students

Into   Shakespeare

Music   appreciation

…

…

…

…

…

…

…

 

【SPL 脚本】


A

B

1

=connect("db")

/连接数据库

2

=A1.query("select * from   Course").keys(ID)

/读取课程表,并设置主键 ID

3

=A1.query("select * from   SelectCourse")

/读取学生选课表

4

=A3.run(COURSE=COURSE.split@cp())

/将选课表中的课程按逗号拆分后赋值给课程字段

5

=A4.max(COURSE.len())

/找到选课最多的数量

6

=create(ID,STUDENT_NAME,   ${A5.("COURSE"+string(~)).concat@c()})

/创建空表,课程列按照最多的数量创建

7

>A4.run(A6.record([ID,STUDENT_NAME]|COURSE.(A2.find(~).Name)))

/循环选课表,将学生 ID、学生姓名以及使用 A.find() 函数查找出的课程名称合并追加到 A6 的表中。

A6的执行结果如下:

ID

STUDENT_NAME

COURSE1

COURSE2

COURSE3

1

Rebecca

Mental   health of College Students

Into   Shakespeare


2

Ashley

Environmental   protection and …

Modern   economics


3

Rachel

Mental   health of College Students

Into   Shakespeare

Music   appreciation

…

…

…

…

…

 

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