如何通过JOIN从另一个表中查找不存在的数据?

发布于 2024-12-05 18:57:52 字数 552 浏览 1 评论 0原文

我有两个表 TABLE1,看起来像:

id      name     address
1       mm     123
2       nn     143

和 TABLE2 w/c 看起来像:

name     age
mm      6
oo      9

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

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

id      name     address
2      nn      143

我已经尝试过这个,但它没有不起作用:

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

它仍在获取现有记录。

I have two tables TABLE1 which looks like:

id      name     address
1       mm     123
2       nn     143

and TABLE2 w/c looks like:

name     age
mm      6
oo      9

I want to get the non existing names by comparing the TABLE1 with the TABLE2.

So basically, I have to get the 2nd row, w/c has a NN name that doesn't exist in the TABLE2, the output should look like this:

id      name     address
2      nn      143

I've tried this but it doesn't work:

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

and it's still getting the existing records.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

栖竹 2024-12-12 18:57:52

INNER JOIN 在这里没有帮助。

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

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

An INNER JOIN doesn't help here.

One way to solve this is by using a LEFT JOIN:

SELECT w.* 
FROM TABLE1 W 
LEFT JOIN TABLE2 V ON W.name = V.name
WHERE ISNULL(V.name);
胡渣熟男 2024-12-12 18:57:52

您需要的关系运算符是半差异,又名 反连接

大多数 SQL 产品缺乏显式的半差分运算符或关键字。标准 SQL-92 没有(它有一个 MATCH(子查询) 半连接谓词,但是,尽管很容易想到其他方式,但 NOT MATCH(子查询) 的语义是与半差异不同;FWIW 真正的关系语言 教程 D 成功使用不匹配半差异)。

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

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

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

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


更新(3年过去了):我已经转向更喜欢 NOT IN (subquery) 因为它更具可读性,如果您担心空值的意外结果(而且您应该担心),请停止使用完全是我多年前做过的。

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

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

The relational operator you require is semi difference a.k.a. antijoin.

Most SQL products lacks an explicit semi difference operator or keyword. Standard SQL-92 doesn't have one (it has a MATCH (subquery) semijoin predicate but, although tempting to think otherwise, the semantics for NOT MATCH (subquery) are not the same as for semi difference; FWIW the truly relational language Tutorial D successfully uses the NOT MATCHING semi difference).

Semi difference can of course be written using other SQL predicates. The most commonly seen are: outer join with a test for nulls in the WHERE clause, closely followed by EXISTS or IN (subquery). Using EXCEPT (equivalent to MINUS in Oracle) is another possible approach if your SQL product supports it and again depending on the data (specifically, when the headings of the two tables are the same).

Personally, I prefer to use EXISTS in SQL for semi difference join because the join clauses are closer together in the written code and doesn't result in projection over the joined table e.g.

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

As with NOT IN (subquery) (same for the outer join approach), you need to take extra care if the WHERE clause within the subquery involves nulls (hint: if WHERE clause in the subquery evaluates UNKNOWN due to the presence of nulls then it will be coerced to be FALSE by EXISTS, which may yield unexpected results).


UPDATE (3 years on): I've since flipped to preferring NOT IN (subquery) because it is more readable and if you are worried about unexpected results with nulls (and you should be) then stop using them entirely, I did many more years ago.

One way in which it is more readable is there is no requirement for the range variables W and V e.g.

SELECT * FROM TABLE1 WHERE name NOT IN ( SELECT name FROM TABLE2 );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文