SQL 为值区间填充缺失值,你想列出整个 20 世纪 80 年代里每年新入职的员工人数,但有一些年份并没有新增员工。你希望返回如下所示的结果集。
SQL 为值区间填充缺失值 问题描述
你想列出整个 20 世纪 80 年代里每年新入职的员工人数,但有一些年份并没有新增员工。你希望返回如下所示的结果集。
SQL 为值区间填充缺失值 解决方案
本解决方案的关键之处在于如何为那些没有新增员工的年份返回 0。如果在一个给定的年份里没有新入职的员工,那么 EMP
表里就不存在对应的行。既然表里不包含这一年,我们该如何为这一年返回计数值 0 呢?本解决方案需要用到外连接操作。我们要拼凑一个包含了所有目标年份的结果集,然后针对 EMP
表执行 COUNT
查询,以判断每一年里是否新增了员工。
DB2
把 EMP
表作为数据透视表(因为它有 14 行数据),并调用内置函数 YEAR
,为 20 世纪 80 年代的每一个年份生成一行数据。然后,外连接 EMP
表,并计算每年新增了多少名员工。
Oracle
把 EMP
表作为数据透视表(因为它有 14
行数据),并调用内置函数 TO_NUMBER
和 TO_CHAR
,为 20 世纪 80 年代的每一个年份生成一行数据。然后,外连接 EMP
表,并计算每年新增了多少名员工。
如果使用的是 Oracle 9i 及后续版本,则不妨使用新提供的 JOIN
子句。
PostgreSQL 和 MySQL
把 T10
表作为数据透视表(因为它有 10 行数据),并调用内置函数 EXTRACT
,为 20 世纪 80 年代的每一个年份生成一行数据。然后,外连接 EMP
表,并计算每年新增了多少名员工。
SQL Server
把 EMP
表作为数据透视表(因为它有 14
行数据),并调用内置函数 YEAR
,为 20 世纪 80 年代的每一个年份生成一行数据。然后,外连接 EMP
表,并计算每年新增了多少名员工。
SQL 为值区间填充缺失值 扩展知识
尽管各个数据库的解决方案在语法上有所不同,做法却并无二致。内嵌视图 X
先找出最早的 HIREDATE
值对应的年份,进而返回 20 世纪 80 年代的每一年。下一步是用最早的年份减去该年份模 10 计算的结果,然后再加上 RN–1
。为了更清楚地了解其工作原理,我们不妨实际运行一下内嵌视图 X
,并分别返回其中涉及的每一个值。下面列出了两个版本的内嵌视图 X
,它们分别使用窗口函数 MIN OVER
(DB2、Oracle 和 SQL Server)和标量子查询(MySQL 和 PostgreSQL)来得到对应的结果集。
内嵌视图 Y
返回每一个 HIREDATE
对应的年份,以及那一年新增的员工人数。
最后,外连接内嵌视图 Y
到内嵌视图 X
,这样即使某一年没有新增员工,也会返回这一年的计数结果。