【问题标题】:MYSQL - select TABLE A rows that are not in Table B except the rows are in TABLE CMYSQL - 选择不在表 B 中的表 A 行,但表 C 中的行除外
【发布时间】:2014-04-08 13:53:48
【问题描述】:

表 A:

dvdID.......dvdTitle

d01........复仇者

d02........复仇者

d03........蜘蛛侠

表 B:

rentID.......dvdID

r01...........d01

r02............d02

r03............d03

表 C:

returnID.......租用ID

t01................r01

我想选择不在表 B 中的 dvd(租用),但在表 C 中(返回) 所以输出应该是这样的:

输出:

dvdID.......dvdTitle

d01........复仇者

你能帮帮我吗?

【问题讨论】:

    标签: mysql sql mysql-select-db


    【解决方案1】:

    您可以在 SQL 条件中使用存在量词,由 EXISTS 关键字表示:

    SELECT *
    FROM TableA a
    WHERE NOT EXISTS (        -- No rental record
        SELECT *
        FROM TableB b
        WHERE b.dvdID=a.dvdID -- The record is for this DVD, and...
          AND NOT EXISTS (    -- ...there is no return record
              SELECT * FROM TableC c WHERE c.rentID=b.rentID
          )
    )
    

    这个查询读起来几乎就像一个结构很差的英文句子,但它解释了正在发生的事情。

    【讨论】:

    • 如果您看到架构和示例数据集,则 tableA 和 tableC 之间没有直接关系,因此这不会给出结果集
    • 使用 OUTER JOIN 比 EXISTS 更快
    • @StanislavL 这可能是十年前的情况,但它甚至不再接近事实。所有非玩具 RDBMS 引擎很久以前就已经解决了这个问题,因此 EXIST 查询几乎与具有连接的等效查询一样快。
    • 不,您的子查询将针对 TableA 中的每一行执行以与 a.id 进行比较。你可以尝试复制自己。
    • 重现案例(创建一个虚拟表并用大量行填充它们并运行您的查询并使用 JOIN 再编写一个查询)。它不依赖于 RDBMS。
    【解决方案2】:

    试试这个,

    SELECT *
    FROM A 
    WHERE (NOT EXISTS (SELECT * FROM B WHERE B.dvdID=A.dvdID))
       OR (EXISTS (SELECT * FROM C,B WHERE C.rentID=B.rentID and B.dvdID=A.dvdID))
    

    这里是SQLFiddle

    【讨论】:

    • 很好,您说得对,先生。也许是因为你使用 SQLFiddle 真的很有帮助,谢谢 :)
    • 很高兴它帮助了你:)
    • 无论如何你能不能给我一些提示(可能是电子书之类的参考资料)来帮助我学习 mySQL?
    • 嗯,我很久以前(大约 5 年前)从我的教学大纲书中学习了 SQL。您只需寻找 SQL 教程,通过练习您就会成为其中的大师。
    • 没有教程能比得上“练习”,只有练习会让你更有信心。只需尝试示例并通过joins, group by, order by, aggregate functions 了解这些是每个 DBMS 中常用的 SQL 基础知识。
    【解决方案3】:

    从您的示例数据集中很明显,您需要其租金存在于 TableC 中的 dvd,为此您可以这样做一个简单的INNER 连接,来自 table3 的最后一个连接将满足来自 table1 的 dvd 的租金存在条件

    select t1.* FROM
    Table1 t1
    LEFT JOIN Table2 USING(dvdID)
    JOIN Table3 USING(rentID)
    

    Fiddle Demo

    【讨论】:

    • 应该是 OUTER join 并且 Table2.id 为 null 来选择不在 Table B 中的 dvd
    • +1 用于替换为 LEFT JOIN 但也应该是 WHERE Table2.id is null
    【解决方案4】:

    试试这个 选项 1

    select * from A 
    where dvdID not in (Select dvdID from B where rentID not in (select rentID from C))
    

    【讨论】:

      【解决方案5】:

      您应该使用JOINS 而不是EXISTS / NOT EXISTS

      SELECT 
          a.*
      FROM TableA a
          LEFT join TableB b
              on b.id=a.id
          LEFT Join TableC c 
              on c.id=a.id
      WHERE
          b.id is null 
          OR (b.id is not null AND c.id is not null)
      

      【讨论】:

        【解决方案6】:

        试试这个:

        SELECT TableA.dvdID, TableA.dvdTitle 
        FROM TableA
        LEFT JOIN TableB ON TableA.dvdID = TableB.dvdID
        LEFT JOIN TableC ON TableC.rentID = TableB.rentID
        WHERE TableB.rentID IS NULL
           OR (TableB.rentID IS NOT NULL
               AND TableC.returnID IS NOT NULL)
        

        【讨论】:

          猜你喜欢
          • 2022-01-09
          • 1970-01-01
          • 2013-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多