【问题标题】:How to write a query showing records from table A without a matching record in table B?如何编写查询显示表 A 中的记录而表 B 中没有匹配记录?
【发布时间】:2009-09-07 15:14:58
【问题描述】:

假设我有两个名为 A(字段:id、phase、name)和 B(字段:id、AID、APHASE、void)的表。

我需要显示 A 中的所有记录,除了 A.id = B.AID 和 A.phase = B.APHASE 和 void = 0 的记录。

环境是 MySQL。

【问题讨论】:

    标签: sql mysql join


    【解决方案1】:
       SELECT *
         FROM `A`
    LEFT JOIN `B`
           ON `A`.`id` = `B`.`id`
        WHERE NOT ( `A`.`id` = `B`.`AID` AND `A`.`phase` = `B`.`APHASE`
                    AND `void` = 0 )
    

    或:

       SELECT *
         FROM `A`
    LEFT JOIN `B`
           ON NOT ( `A`.`id` = `B`.`AID`
                    AND `A`.`phase` = `B`.`APHASE`
                    AND `void` = 0 )
    

    不保证第二个确实有效,我只是想到了它

    【讨论】:

    • 嘿 - 这两个表是在 a.id = b.id 上加入,还是在 'a.id = b.aid' 上加入?这个问题并不清楚 - 但你的答案是假设 id 行加入,而命名则不然。
    • 我不太确定,但我认为第二个陈述描述了这个问题。如果它不能正常工作,effkay 可以随时回复
    • 有一个“他已经做过”的元素 - 你的答案被选中。第二个选项可能应该在 SELECT 列表中列出 A.*。我担心结果的基数(请参阅对作者“答案”的评论)。而且我认为“AND void = 0”位应该在“NOT (...)”括号内。
    【解决方案2】:
    SELECT 
        id, phase, name 
    FROM A 
    WHERE NOT EXISTS 
        (SELECT id FROM B WHERE AID=A.id AND APHASE=A.phase AND void=0)
    

    【讨论】:

      【解决方案3】:
      SELECT  *
      FROM    A
      WHERE   NOT EXISTS
              (
              SELECT  NULL
              FROM    B
              WHERE   b.aid = a.id
                      AND b.aphase = a.phase
                      AND b.void = 0
              )
      

      请注意,此查询将始终返回来自A 的每一行恰好是10 次。

      如果B (aid, aphase) 不是UNIQUELEFT JOIN 可以多次从A 返回行。

      这些查询具有不同的语义,因此选择正确的查询是有效性问题,而不是性能问题。

      就性能而言,MySQL 将始终使用A 作为前导表,因为它无法以除NESTED LOOPS 之外的其他方式进行连接。

      由于EXISTS 总是会在找到第一个匹配记录后立即返回,所以EXISTS 查询总是比LEFT JOIN 更有效(因为它至少不晚于LEFT JOIN 返回),以从A返回最多一条记录为代价。

      【讨论】:

      • NOT EXISTS 可能会很慢
      • @knittl:在MySQL(即MySQL)中,它不会比LEFT JOIN(即LEFT JOIN)慢。
      【解决方案4】:

      我猜是固定的:\

      从 A、B 中选择 *

      在哪里

      not(A.id = B.AID and A.phase = B.APHASE and void = 0)

      我变老了:|

      【讨论】:

      • 不是一个好的解决方案。忽略阶段并暂时无效。假设表A中有一行id = 1,表B中有三行(id = 1,aid = 1),(id = 2,aid = 1),(id = 3,aid = 2 )。此查询将生成结果行,但不应回答问题。 NOT EXISTS 查询不会生成任何行 - 这是正确的结果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多