【问题标题】:Using information from one table to find if the info exists in another table使用一个表中的信息来查找该信息是否存在于另一个表中
【发布时间】:2011-12-06 02:01:38
【问题描述】:

我有 2 张桌子:

广告:

+------+---------------+
|  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 表中分配的所有行的查询

【问题讨论】:

标签: mysql sql anti-join


【解决方案1】:

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

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

【讨论】:

  • “需要”?与 SQL 中的大多数事情一样,执行关系非存在限定的方法不止一种。看我的回答。
【解决方案2】:

您需要的关系运算符是半差分,又名antijoin

大多数 SQL 产品都缺少显式的半连接运算符或关键字。标准 SQL-92 没有一个(它有一个 MATCH (subquery) semijoin 谓词,但是,虽然很容易不这么想,但 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 子句包含空值,则需要格外小心(提示:如果子查询中的WHERE 子句评估为UNKNOWN,因为如果 null 存在,则 EXISTS 将强制它为 FALSE,这可能会产生意想不到的结果。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

      有关左连接的更多信息,请咨询here

      【讨论】:

        【解决方案5】:

        试试这个:

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

        【讨论】:

        • 您的查询中有几个拼写错误:'assigned_ad' 和 'om'
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-17
        • 1970-01-01
        • 2021-02-19
        相关资源
        最近更新 更多