【问题标题】:The purpose of SQL's EXISTS and NOT EXISTSSQL 的 EXISTS 和 NOT EXISTS 的目的
【发布时间】:2011-05-26 19:44:50
【问题描述】:

我时不时地看到这些被使用,但它似乎从来没有通过使用 normal 连接或子查询来表现得同样好,甚至更好。

我认为它们具有误导性(与传统的连接和子查询相比,它们可能更难以准确可视化),经常被误解(例如,在 EXISTS/NOT EXISTS 子查询中使用 SELECT *SELECT 1 的行为相同),并且根据我有限的经验,执行速度较慢。

有人可以描述和/或提供一个例子吗?请注意,由于它们的执行和性能可能取决于平台,因此我对它们在 MySQL 中的使用特别感兴趣。

【问题讨论】:

标签: sql mysql subquery exists not-exists


【解决方案1】:

我时不时地看到这些被使用,但似乎从来没有任何事情不能通过使用普通的连接或子查询来表现得同样好,甚至更好。

这篇文章(虽然SQL Server相关):

您可能会感兴趣。

简而言之,JOIN 是一个集合操作,而EXISTS 是一个谓词。

换句话说,这些查询:

SELECT  *
FROM    a
JOIN    b
ON      some_condition(a, b)

对比

SELECT  *
FROM    a
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    b
        WHERE   some_condition(a, b)
        )

不一样:前者可以从a返回多条记录,而后者不能。

他们的对应对象,NOT EXISTSLEFT JOIN / IS NULL,在逻辑上是相同的,但在性能方面并不相同。

其实在SQL Server中,前者可能效率更高:

【讨论】:

    【解决方案2】:

    您不能 [轻松] 在 UPDATE 语句中使用连接,因此 WHERE EXISTS 在那里工作得很好:

    UPDATE mytable t
       SET columnX = 'SomeValue'
     WHERE EXISTS 
       (SELECT 1 
          FROM myothertable ot
         WHERE ot.columnA = t.columnY
           AND ot.columnB = 'XYX'
       );
    

    编辑:基于 Oracle 而不是 MySQL,是的,有一些方法可以使用内联视图来实现,但恕我直言,这更简洁。

    【讨论】:

    • BQ:在 MySQL 中,我很确定你可以写成 UPDATE mytable t JOIN myothertable ot ON ot.columnA = t.columnY SET columnX = 'SomeValue' WHERE ot.columnB = 'XYX'
    • 这是一个有趣的观察,但我特别关心的是 MySQL。
    【解决方案3】:

    如果主查询返回的行数比您要查找它们的表少得多。示例:

    SELECT st.State
    FROM states st
    WHERE st.State LIKE 'N%' AND EXISTS(SELECT 1 FROM addresses a WHERE a.State = st.State)
    

    使用连接执行此操作会慢得多。或者一个更好的例子,如果您想搜索一个项目是否存在于多个表中的 1 个中。

    【讨论】:

    • 如果您坚持强制 join 顺序,我认为使用 STRAIGHT JOIN 会同样有效,甚至更多。例如,SELECT st.State FROM states st STRAIGHT_JOIN addresses a ON a.State = st.State WHERE st.State LIKE 'N%'
    • @Riedsio 我不想加入。假设地址表中每个州都有很多记录。
    • 我想我现在明白了。我可以看到您如何在 EXISTS 子句中放置一个 LIMIT 1 得到一些改进(或者至少不会受到伤害)——即 ... AND EXISTS(SELECT 1 FROM addresses a WHERE a.State = st.State限制 1)
    猜你喜欢
    • 2021-08-29
    • 2015-02-17
    • 1970-01-01
    • 2016-07-22
    • 2013-02-10
    • 1970-01-01
    • 2013-04-17
    • 2021-05-29
    • 2010-11-13
    相关资源
    最近更新 更多