SQL 从多个表中返回缺失值

SQL 从多个表中返回缺失值,你想从多个表中返回缺失值。找到存在于 DEPT 表而不存在于 EMP 表的数据(即没有员工的部门)需要使用外连接。考虑下面的查询语句,该查询返回了 DEPT 表中所有的 DEPTNODNAME,以及每个部门里全部员工的名字(如果这个部门有员工的话)。

SQL 从多个表中返回缺失值 问题描述

你想从多个表中返回缺失值。找到存在于 DEPT 表而不存在于 EMP 表的数据(即没有员工的部门)需要使用外连接。考虑下面的查询语句,该查询返回了 DEPT 表中所有的 DEPTNODNAME,以及每个部门里全部员工的名字(如果这个部门有员工的话)。

select d.deptno,d.dname,e.ename
  from dept d left outer join emp e
    on (d.deptno=e.deptno)
 
    DEPTNO DNAME          ENAME
---------- -------------- ----------
        20 RESEARCH       SMITH
        30 SALES          ALLEN
        30 SALES          WARD
        20 RESEARCH       JONES
        30 SALES          MARTIN
        30 SALES          BLAKE
        10 ACCOUNTING     CLARK
        20 RESEARCH       SCOTT
        10 ACCOUNTING     KING
        30 SALES          TURNER
        20 RESEARCH       ADAMS
        30 SALES          JAMES
        20 RESEARCH       FORD
        10 ACCOUNTING     MILLER
        40 OPERATIONS

最后一行是 OPERATIONS 部门,这个部门虽然没有员工,却也出现在了查询结果中,这是因为 DEPT 表外连接了 EMP 表。现在假设有一个员工不属于任何部门,你将如何返回以上结果集,并且包含那个不属于任何部门的员工呢?换句话说,你希望在同一个查询语句里既外连接到 EMP 表又外连接到 DEPT 表。在创建了新的员工数据之后,第一次尝试可能如下所示。

insert into emp (empno,ename,job,mgr,hiredate,sal,comm,deptno)
select 1111,'YODA','JEDI',null,hiredate,sal,comm,null
  from emp
 where ename = 'KING'
 
select d.deptno,d.dname,e.ename
  from dept d right outer join emp e
    on (d.deptno=e.deptno)
 
    DEPTNO DNAME          ENAME
---------- -------------- ----------
        10 ACCOUNTING     MILLER
        10 ACCOUNTING     KING
        10 ACCOUNTING     CLARK
        20 RESEARCH       FORD
        20 RESEARCH       ADAMS
        20 RESEARCH       SCOTT
        20 RESEARCH       JONES
        20 RESEARCH       SMITH
        30 SALES          JAMES
        30 SALES          TURNER
        30 SALES          BLAKE
        30 SALES          MARTIN
        30 SALES          WARD
        30 SALES          ALLEN
                          YODA

以上外连接查询包含了那个新的员工,却丢失了先前结果集里的 OPERATIONS 部门。最终的结果集应该既包括 YODA,也包括 OPERATIONS,如下所示。

    DEPTNO DNAME          ENAME
---------- -------------- ----------
        10 ACCOUNTING     CLARK
        10 ACCOUNTING     KING
        10 ACCOUNTING     MILLER
        20 RESEARCH       ADAMS
        20 RESEARCH       FORD
        20 RESEARCH       JONES
        20 RESEARCH       SCOTT
        20 RESEARCH       SMITH
        30 SALES          ALLEN
        30 SALES          BLAKE
        30 SALES          JAMES
        30 SALES          MARTIN
        30 SALES          TURNER
        30 SALES          WARD
        40 OPERATIONS
                           YODA

SQL 从多个表中返回缺失值 解决方案

使用全外连接(full outer join),基于一个共同值从两个表中返回缺失值。
DB2、MySQLPostgreSQLSQL Server
使用显式的全外连接命令从两个表中返回缺失的行以及相匹配的行。

1 select d.deptno,d.dname,e.ename
2   from dept d full outer join emp e
3     on (d.deptno=e.deptno)

或者,也可以合并两个外连接的查询结果。

1 select d.deptno,d.dname,e.ename
2   from dept d right outer join emp e
3     on (d.deptno=e.deptno)
4  union
5 select d.deptno,d.dname,e.ename
6   from dept d left outer join emp e
7     on (d.deptno=e.deptno)

Oracle
对于 Oracle 9i 数据库及其后续版本,上述解决方案仍然适用。除此之外,我们也可以使用 Oracle 专有的外连接语法。对于 Oracle 8i 数据库及更早的版本,只能使用专有语法实现外连接。

1 select d.deptno,d.dname,e.ename
2   from dept d, emp e
3  where d.deptno = e.deptno(+)
4  union
5 select d.deptno,d.dname,e.ename
6   from dept d, emp e
7  where d.deptno(+) = e.deptno

SQL 从多个表中返回缺失值 扩展知识

全外连接查询其实就是合并两个表的外连接查询的结果集。为了理解全外连接背后的运行原理,直接执行每一个外连接查询,然后合并其查询结果集即可。下面的查询找出了 DEPT 表里与 EMP 表相匹配的所有行(如果存在的话)。

select d.deptno,d.dname,e.ename
  from dept d left outer join emp e
    on (d.deptno = e.deptno)
 
DEPTNO DNAME          ENAME
------ -------------- ----------
    20 RESEARCH       SMITH
    30 SALES          ALLEN
    30 SALES          WARD
    20 RESEARCH       JONES
    30 SALES          MARTIN
    30 SALES          BLAKE
    10 ACCOUNTING     CLARK
    20 RESEARCH       SCOTT
    10 ACCOUNTING     KING
    30 SALES          TURNER
    20 RESEARCH       ADAMS
    30 SALES          JAMES
    20 RESEARCH       FORD
    10 ACCOUNTING     MILLER
    40 OPERATIONS

接下来的这个查询找出了 EMP 表里与 DEPT 表相匹配的所有行(如果存在的话)。

select d.deptno,d.dname,e.ename
  from dept d right outer join emp e
    on (d.deptno = e.deptno)

DEPTNO DNAME          ENAME
------ -------------- ----------
    10 ACCOUNTING     MILLER
    10 ACCOUNTING     KING
    10 ACCOUNTING     CLARK
    20 RESEARCH       FORD
    20 RESEARCH       ADAMS
    20 RESEARCH       SCOTT
    20 RESEARCH       JONES
    20 RESEARCH       SMITH
    30 SALES          JAMES
    30 SALES          TURNER
    30 SALES          BLAKE
    30 SALES          MARTIN
    30 SALES          WARD
    30 SALES          ALLEN
                      YODA

合并上面的两个查询结果,就可以得到最终的结果集。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程