【问题标题】:Why aren't "NOT IN" and "NOT EXISTS" working?为什么“不在”和“不存在”不起作用?
【发布时间】:2020-08-07 11:42:02
【问题描述】:

我尝试了几种不同的方式来实现这一点,但我做不到。我正在尝试找出今年尚未预约的客户的 ID。

我的第一个查询需要 永远,并且大部分时间都会超时:

SELECT c.clientId
FROM clients c
WHERE NOT EXISTS (
   SELECT a.appointmentId FROM appointments a WHERE a.date >= "2020-02-15" AND c.clientId = a.clientId)

我的第二个查询非常快,但这可能是因为它没有考虑 NOT IN。结果显示的结果与我在没有 NOT EXISTS 的情况下运行查询相同。我认为这意味着我没有正确匹配 a.clientId = c.clientId。但是,我似乎无法弄清楚如何让它发挥作用。

SELECT c.clientId
FROM clients c
WHERE c.clientId NOT IN (
    SELECT a.appointmentId FROM appointments a WHERE a.date >= "2020-02-15")

我也尝试了第三种方法,但没有成功,它返回一个空集:

SELECT c.clientId
FROM clients c
LEFT JOIN appointments a
ON a.clientId = c.clientId
WHERE a.appointmentId IS NULL
AND a.date >= '2020-02-15'

提前致谢!

【问题讨论】:

    标签: mysql not-exists notin


    【解决方案1】:

    您的第二个查询的问题是您将client 中的clientIdappointments 中的appointmentId 进行比较,因此不太可能进行任何过滤。应该写成

    SELECT clientId
    FROM clients
    WHERE clientId NOT IN (
        SELECT clientId FROM appointments WHERE date >= "2020-02-15")
    

    您的第三个查询的问题是WHERE 子句中的a.date >= '2020-02-15' 条件有效地将您的LEFT JOIN 转换为INNER JOIN(请参阅manual),因此a.appointmentId IS NULL 永远不会为真。您需要将date 比较添加到JOIN 条件:

    SELECT c.clientId
    FROM clients c
    LEFT JOIN appointments a
    ON a.clientId = c.clientId AND a.date >= '2020-02-15'
    WHERE a.appointmentId IS NULL
    

    注意如果all你想要的是clientId值,你根本不需要使用clients表:

    SELECT clientId
    FROM appointments
    GROUP BY clientId
    HAVING MAX(date) < '2020-02-15'
    

    Demo on dbfiddle

    【讨论】:

    • 第二个查询很好。我不敢相信我玩了一下午就错过了。但即使进行了修改,它仍然返回与没有 NOT IN 子句相同的数字。现在运行第三个查询,这需要一段时间,但数据库非常大。如果它有效,我会标记它!
    • 是的,您对第三个查询的修改有效。我真的很感谢你的帮助。我无法再标记 3 分钟的答案,但想让你知道。即使我有 WHERE 1 NOT IN...,第二个查询也会做同样的事情,所以我不确定它为什么决定完全忽略它。
    • @radleybobins 我添加了一个演示,它显示了第二个查询工作。此外,我还添加了另一个备用查询,如果您想要的 allclientId 值,它应该会更快。
    • 我知道您应该严格遵守 cmets 的业务,但我只是想再次感谢您,并为没有回复您更新的演示而道歉。我因食物中毒而倒下,我刚刚恢复正常。您的回答和 cmets 非常有帮助,我非常感谢您让我度过难关。
    • @radleybobins 完全没有问题 - 很遗憾听到食物中毒的消息,我知道这有多糟糕。无论如何,我很高兴它有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 2016-08-01
    • 2016-10-29
    • 2018-11-12
    • 2022-01-04
    • 2016-12-31
    相关资源
    最近更新 更多