如何通过JOIN从其他表中find不存在的数据?

我有两个表TABLE1,如下所示:

id name address 1 mm 123 2 nn 143 

和TABLE2 W / C看起来像:

 name age mm 6 oo 9 

我想通过比较TABLE1TABLE2来获取不存在的名称。

所以基本上,我必须得到第二行,W / C有一个NN名称不存在于TABLE2 ,输出应该是这样的:

 id name address 2 nn 143 

我试过这个,但不起作用:

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

而且它仍然得到现有的logging。

INNER JOIN在这里没有帮助。

解决这个问题的方法之一是使用LEFT JOIN

 SELECT w.* FROM TABLE1 W LEFT JOIN TABLE2 V ON W.name = V.name WHERE ISNULL(V.name); 

您需要的关系运算符是半差异aka 反连接 。

大多数SQL产品缺less显式的半差异运算符或关键字。 标准的SQL-92没有一个(它有一个MATCH (subquery) semijoin谓词,但是,尽pipe有其他的想法,但是NOT MATCH (subquery)的语义与半差别不一样; FWIW真正的关系语言教程D成功使用NOT MATCHING半差异)。

当然可以使用其他SQL谓词来编写半差异。 最常见的是:在WHERE子句中用外部连接进行空值testing,紧接着是EXISTSIN (subquery) 。 使用EXCEPT (相当于Oracle中的MINUS )是另一种可能的方法,只要您的SQL产品支持该方法,并且依赖于数据(具体来说,两个表的标题相同)。

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

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

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


更新(3年以上):我已经翻转,宁愿NOT IN (subquery)因为它更可读,如果你担心与空值意想不到的结果(你应该),然后停止使用它们,我做了更多多年前。

一种更可读的方法是不需要范围variablesWV例如,

 SELECT * FROM TABLE1 WHERE name NOT IN ( SELECT name FROM TABLE2 ); 
Interesting Posts