使用来自一个表的信息来查找该信息是否存在于另一个表中

时间:2011-10-12 11:57:25

标签: mysql sql anti-join

我有两张桌子:

广告:

+------+---------------+
|  ID  |  Name         |
+------+---------------+
| 1    |   Item 1      |
| 2    |   Item 2      |
| 3    |   Item 3      |
| 4    |   Item 4      |
| 5    |   Item 5      |
+------+---------------+

assigned_ads:

+------+-----------+--------------+
|  ID  |   ad_id   |  location    |
+------+-----------+--------------+
|  1   |    3      |  place 1     |
|  2   |    2      |  place 2     |
|  3   |    1      |  place 3     |
+------+-----------+--------------+

正如你所看到的;广告1,2和3都分配到一个位置。我需要的是一个查询,它获取ads表中未在assigned_ads表中分配的所有行

5 个答案:

答案 0 :(得分:4)

您需要使用LEFT OUTER JOIN来执行此操作,如下所示:

SELECT * 
FROM ads a
LEFT JOIN assigned_ads aa ON a.ID = aa.ad_id
WHERE aa.location IS NULL

答案 1 :(得分:1)

您还可以使用NOT EXISTS运算符:

SELECT * 
FROM ads a
WHERE NOT EXISTS
(SELECT * FROM assigned_ads aa WHERE a.ID = aa.ad_id)

答案 2 :(得分:1)

您需要的关系运算符是半差异a.k.a. antijoin

大多数SQL产品缺少明确的半连接运算符或关键字。标准SQL-92没有一个(它有一个MATCH (subquery)半连接谓词但是,虽然很想不这么认为,NOT MATCH (subquery)的语义与半差异的语义不同; FWIW是真正的关系语言Tutorial D成功使用NOT MATCHING半差异。)

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

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

SELECT *
  FROM ads 
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM assigned_ads
                    WHERE ads.ID = assigned_ads.ID
                  );

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

答案 3 :(得分:0)

试试这个:

SELECT * 
FROM ads a
WHERE a.id NOT IN (SELECT ad_id FROM assigned_ads)

答案 4 :(得分:0)

只是用户左连接查询并将左表id与null匹配。 你查询应该是这样的

select * from ads ad left join assigned_ad a_ad ON a_ad.ad_id = ad.id where a_ad.id is null

有关左连接的详细信息,请参阅here