SQL 如何查询每个分组都出现的字段值

 

关键词导读:按周分组 各组交集 组间计算

数据分组以后,要找出在每个分组中都出现的某个字段值。

SQL来解决这个问题并不容易!

SQL缺少单纯的分组操作,只能返回各分组的统计值,而不能对各组的成员再进行更细的交、差、并等集合运算。要解决这种问题就需要多层嵌套子查询来变相地实现。

举个例子:查询每周都加班的员工以进行表彰。现有加班数据表OVERTIME_WORK数据如下:

WORKDATE

NAME

2019-07-01

Tom

2019-07-02

John

2019-07-03

Tom

2019-07-04

Cart

2019-07-08

Tom

2019-07-09

Jordan

2019-07-10

Kate

2019-07-10

John

2019-07-15

Leon

2019-07-16

John

2019-07-17

Tom

2019-07-18

John

2019-07-22

Jim

2019-07-23

Tom

2019-07-24

John

2019-07-25

Cart

 

Oracle为例,用SQL写出来是这样:

WITH A AS

       (SELECT COUNT(*) NUM FROM

        (SELECT DISTINCT TO_CHAR(WORKDATE,'IW') FROM OVERTIME_WORK )

        ),

B AS

        (SELECT TO_CHAR(WORKDATE,'IW') W, NAME

        FROM OVERTIME_WORK

        GROUP BY TO_CHAR(WORKDATE,'IW'), NAME

        ),

C AS

       (SELECT NAME, COUNT(*) NUM FROM B GROUP BY NAME )

SELECT NAME FROM C WHERE NUM=(SELECT NUM FROM A);

这里的A查出共有几周,B查出每周加班的不同员工,C查出B里各员工的出现次数,最后从C里选出出现次数与总周数相等的员工。解决思路比较绕,这种SQL既难写又难懂。

 

集算器的SPL语言支持集合运算,解决这个问题就会简单很多,计算出每周加班员工的交集即可,只需1行代码:

connect("mydb").query("SELECT * FROM OVERTIME_WORK").group((WORKDATE-date("2019-07-01"))\7).(~.(NAME)).isect()

【问题延伸】

* 查询每周至少加班两次的员工

* 查询每个月消费金额均排在前20名的客户名称

 

SPL 擅长解决这类分组子集和组内有序计算,请阅《计算各组前 N 行》《组内运算》《行间计算》《集合》

集算器 SPL 是解决 SQL 难题的专业脚本语言,它语法简单,符合自然思维,是天然分步、层次清晰的面向过程计算语言。它采用与数据库无关的统一语法,编写的算法可在数据库间无缝迁移。它是桌面级计算工具,即装即用,配置简单,调试功能完善,可设置断点、单步执行,每步执行结果都可查看。请参阅SQL 解题手

SPL也能很方便地嵌入到JAVA应用,可参考Java 如何调用 SPL 脚本》

具体使用方法可参考 《如何使用集算器》