如何通过JOIN从其他表中find不存在的数据?
我有两个表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
而且它仍然得到现有的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,紧接着是EXISTS
或IN (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)
因为它更可读,如果你担心与空值意想不到的结果(你应该),然后停止使用它们,我做了更多多年前。
一种更可读的方法是不需要范围variablesW
和V
例如,
SELECT * FROM TABLE1 WHERE name NOT IN ( SELECT name FROM TABLE2 );