SQL 从一个表检索与另一个表不相关的行

SQL 从一个表检索与另一个表不相关的行,两个表有相同的键,你想在一个表里查找与另一个表不相匹配的行。例如,你想找出哪些部门没有员工。结果集如下所示。

SQL 从一个表检索与另一个表不相关的行 问题描述

两个表有相同的键,你想在一个表里查找与另一个表不相匹配的行。例如,你想找出哪些部门没有员工。结果集如下所示。

    DEPTNO DNAME          LOC
---------- -------------- -------------
        40 OPERATIONS     BOSTON

如果想要找到每一个员工就职的部门,需要基于 EMP 表和 DEPT 表的 DEPTNO 列进行相等连接查询。DEPTNO 是两个表都有的列。不幸的是,相等连接无法找到哪些部门没有员工。这是因为,针对 EMP 表和 DEPT 表做相等连接操作,将返回满足连接条件的所有行。相反,你只想从 DEPT 表里找出那些不满足连接条件的行。
本问题乍看起来和前一个实例相同,但其实它们之间有微妙的差别。不同之处在于,前一个实例仅仅返回了没有出现在 EMP 表中的部门编号。然而,本实例可以很方便地从 DEPT 表中获取其他列。

SQL 从一个表检索与另一个表不相关的行 解决方案

基于共同列把两个表连接起来,返回一个表的所有行,不论这些行在另一个表里是否存在匹配行。然后,只保留那些不匹配的行即可。
DB2、MySQLPostgreSQLSQL Server
使用外连接并过滤掉 Null 值(关键字 OUTER 是可选的)。

1 select d.*
2   from dept d left outer join emp e
3     on (d.deptno = e.deptno)
4  where e.deptno is null

Oracle
对于 Oracle 9i 及其后续版本,上述解决方案仍然适用。当然,你也可以使用 Oracle 专有的外连接语法。

1 select d.*
2   from dept d, emp e
3  where d.deptno = e.deptno (+)
4    and e.deptno is null

Oracle 8i 数据库及更早的版本只能使用上述专有语法(注意,圆括号里是 +)来完成外连接操作。

SQL 从一个表检索与另一个表不相关的行 扩展知识

这个解决方案使用了外连接,并且只保留不匹配的行。这种操作有时候被称为反连接(anti-join)。为了更好地理解反连接,我们先来看一下没有过滤掉 Null 值的结果集。

select e.ename, e.deptno as emp_deptno, d.*
  from dept d left join emp e
    on (d.deptno = e.deptno)
 
ENAME      EMP_DEPTNO     DEPTNO DNAME          LOC
---------- ---------- ---------- -------------- -------------
SMITH              20         20 RESEARCH       DALLAS
ALLEN              30         30 SALE           CHICAGO
WARD               30         30 SALES          CHICAGO
JONES              20         20 RESEARCH       DALLAS
MARTIN             30         30 SALES          CHICAGO
BLAKE              30         30 SALES          CHICAGO
CLARK              10         10 ACCOUNTING     NEW YORK
SCOTT              20         20 RESEARCH       DALLAS
KING               10         10 ACCOUNTING     NEW YORK
TURNER             30         30 SALES          CHICAGO
ADAMS              20         20 RESEARCH       DALLAS
JAMES              30         30 SALES          CHICAGO
FORD               20         20 RESEARCH       DALLAS
MILLER             10         10 ACCOUNTING     NEW YORK
                              40 OPERATIONS     BOSTON

注意,最后一行的 EMP.ENAMEEMP_DEPTNO 都是 Null 值。这是因为没有员工在编号为 40 的部门工作。该解决方案使用 WHERE 子句,只保留了 EMP_DEPTNONull 值的行(这样只留下 DEPT 表中无法与 EMP 表相匹配的行)。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程