6

我有两个表 TABLE1 看起来像:

id      name     address
1       mm     123
2       nn     143

和 TABLE2 w/c 看起来像:

name     age
mm      6
oo      9

我想通过将TABLE1与进行比较来获得不存在的名称TABLE2

所以基本上,我必须得到第二行,w/c 有一个 NN 中不存在的名称,TABLE2输出应该如下所示:

id      name     address
2      nn      143

我已经尝试过了,但它不起作用:

SELECt  w.* FROM TABLE1 W INNER JOIN TABLE2 V
  ON W.NAME <> V.NAME

它仍在获取现有记录。

4

2 回答 2

6

INNER JOIN这里没有帮助。

解决此问题的一种方法是使用LEFT JOIN

SELECT w.* 
FROM TABLE1 W 
LEFT JOIN TABLE2 V ON W.name = V.name
WHERE ISNULL(V.name);
于 2011-09-21T04:28:22.137 回答
2

您需要的关系运算符是 semi Difference aka antijoin

大多数 SQL 产品缺少显式的半差分运算符或关键字。标准 SQL-92 没有(它有一个MATCH (subquery)semijoin 谓词,但是,虽然很容易不这么想,但语义NOT MATCH (subquery)与半差分不同;FWIW 真正的关系语言教程 D成功地使用了NOT MATCHING半差分)。

半差分当然可以使用其他 SQL 谓词来编写。最常见的是:在WHERE子句中测试空值的外连接,紧随其后的是EXISTSor IN (subquery)。如果您的 SQL 产品支持并且再次取决于数据(特别是当两个表的标题相同时),使用EXCEPT(相当于在 Oracle 中)是另一种可能的方法。MINUS

就个人而言,我更喜欢EXISTS在 SQL 中使用半差分连接,因为连接子句在书面代码中更接近,并且不会导致连接表上的投影,例如

SELECT *
  FROM TABLE1 W
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM TABLE2 V
                    WHERE W.NAME = V.NAME
                  );

与(与外连接方法相同)一样,如果子查询中的子句涉及空值,NOT IN (subquery)则需要格外小心(提示:如果子查询中的子句由于存在空值而评估为 UNKNOWN,那么它将被强制为 FALSE ,这可能会产生意想不到的结果)。WHEREWHEREEXISTS


更新(3 年后):我已经转向更喜欢NOT IN (subquery),因为它更具可读性,如果您担心空值的意外结果(您应该)那么完全停止使用它们,我在很多年前就这样做了。

一种更具可读性的方法是不需要范围变量WV例如

SELECT * FROM TABLE1 WHERE name NOT IN ( SELECT name FROM TABLE2 );
于 2011-09-21T07:43:40.717 回答