【问题标题】:MySQL WHERE EXISTS evaluating to true for all recordsMySQL WHERE EXISTS 对所有记录评估为真
【发布时间】:2014-11-20 23:18:02
【问题描述】:

我正在尝试运行一个查询来检索子查询中存在的表中的所有记录。

但是,它会返回所有记录,而不是我期望的记录。

这里是查询:

SELECT DISTINCT x FROM T1 WHERE EXISTS 
      (SELECT * FROM T1 NATURAL JOIN T2 WHERE T2.y >= 3.0);

我已尝试测试子查询,它返回符合我的约束的正确记录数。

但是当我运行整个查询时,它会返回子查询中不应该存在的记录。

为什么 EXISTS 对 T1 中的所有记录都评估为真?

【问题讨论】:

    标签: mysql sql subquery where exists


    【解决方案1】:

    您需要一个相关的子查询,而不是子查询中的联接。目前还不清楚正确的相关性子句是什么,但是是这样的:

    SELECT DISTINCT x
    FROM T1
    WHERE EXISTS (SELECT 1 FROM T2 WHERE T2.COL = T1.COL AND T2.y >= 3.0);
    

    您的查询有一个常规子查询。每当它返回至少一行时,exists 就为真。因此,必须至少有一个匹配行。这个版本“逻辑地”运行外部T1 中每一行的子查询。

    【讨论】:

    • 那工作!!谢谢,我会尽快接受这个答案。我确实对相关与加入有些混淆。为什么头脑总是表现得像真的一样?
    • 你的行为一直都是真的,因为第二个查询是完全独立的,因此正在评估的表中的每条记录都存在某些东西。即无法将子查询结果与 T1 中的任何特定行对齐,因此返回所有行。
    【解决方案2】:

    问:为什么 EXISTS 对 T1 中的所有记录都评估为真?

    答:因为子查询返回一行,完全独立于外部查询中的任何内容。

    EXISTS 谓词只是检查子查询是否返回一行,并返回布尔值 TRUE 或 FALSE。

    你会得到相同的结果:

    SELECT DISTINCT x FROM T1 WHERE EXISTS (SELECT 1)
    

    (唯一的区别是如果该子查询没有返回至少一行,那么您将不会在外部查询中返回任何行。)

    子查询返回的行与外部查询中的行之间没有关联。


    我预计您还有其他问题要问。答案实际上取决于您想要返回的结果集。

    如果您想从 T1 返回在 T2 中有一些“匹配”行的行,您可以使用 NOT EXISTS (correlated subquery)

    或者,您也可以使用连接操作返回等效结果,例如:

     SELECT DISTINCT T1.x 
       FROM T1
    NATURAL
       JOIN T2 
      WHERE T2.y >= 3.0
    

    【讨论】:

    • 谢谢!是的,在看到上面的例子后,我对 EXISTS 的工作原理有了更好的理解。添加外部和内部查询之间的相关性后,我得到了正确的结果!
    • @JulioReyes:我将举一个相关子查询的示例,但NATURAL JOIN 实际上是“隐藏”了您在T1 和@987654327 中“匹配”的列的名称@。我个人的偏好是避免使用NATURAL JOIN,因为如果当 T1 包含列 (fa, fee, fi, fo, fum) 并且 T2 包含列 (doh, ray, me, fa) 时它正在“工作”......使用与名称匹配的名称向 T1 或 T2 添加另一列另一个表中的现有列将“破坏”查询。例如,将列 me 添加到 T1 将改变 NATURAL JOIN 操作的作用。
    • 另外,使用 NATURAL JOIN,为了“弄清楚”哪些列被“匹配”,读者需要比较 T1 和 T2 的定义,以找到所有具有同名。 (我更喜欢编写我的查询,以便在有人向表中添加列时它们不会“中断”,并且不会减少读者查阅表定义以找出正在引用的列名的必要性。
    • 我明白了,这很有意义。将子查询从连接更改为关联后,我的查询不再使用自然连接。我肯定会避免使用自然连接,因为我知道如果添加/更改表列,它们会如何中断。再次感谢!
    【解决方案3】:

    它不起作用,因为外部查询和正在使用的子查询之间没有关联。下面有and T1.id = T2.id形式的关联

    SELECT DISTINCT x 
    FROM T1 
    WHERE EXISTS  ( SELECT 1 FROM T2 WHERE T2.y >= 3.0 and T1.id = T2.id)
    ;
    

    但是,在不知道数据的情况下,我希望您不需要在该查询中使用“distinct”,这样会产生相同的结果:

    SELECT x 
    FROM T1 
    WHERE EXISTS  ( SELECT 1 FROM T2 WHERE T2.y >= 3.0 and T1.id = T2.id)
    ;
    

    另一种可能需要不同的替代方法是第二个查询的后半部分的变体

    SELECT DISTINCT x FROM T1 NATURAL JOIN T2 WHERE T2.y >= 3.0
    

    【讨论】:

    • 感谢现在更有意义了!我没有做任何关联。
    【解决方案4】:

    您可以使用 INNER JOIN 来获得您想要去的地方:

    SELECT DISTINCT T1.X
      FROM T1
      INNER JOIN T2
        ON T2.COL = T1.COL
      WHERE T2.Y > 3.0
    

    分享和享受。

    【讨论】:

      猜你喜欢
      • 2023-04-03
      • 2016-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多