LEFT JOIN 无法替换 NOT EXISTS MYSQL
LEFT JOIN not working to replace a NOT EXISTS MYSQL
我有一个名为 Documents 的 table 和一个名为 Notes 的 table 用于存储文档的注释。我需要获取所有没有状态为 2 或 3 的注释的文档。
SELECT * FROM Documents
WHERE NOT EXISTS (
SELECT docID FROM Notes WHERE docId = id AND status IN (2, 3)
)
这非常慢,但可以。我尝试进行内部连接,但如果只有一张纸条的状态不是 2 或 3,它仍会显示文档。我需要它只显示在任何注释中都没有出现 2 或 3 的文档。
谁能帮忙!?谢谢!
一种方法:
SELECT *, COUNT(docID)
FROM Documents
LEFT JOIN Notes ON docID = id AND (status IN (2,3))
GROUP BY id
HAVING COUNT(docID) = 0
如果 status=2 或 status=3,则计数将为非零,并且 having
将完全消除文档。
反加入 是一种熟悉的 SQL 模式。
使用该模式,我们使用外连接操作 return 所有行,以及匹配的行,包括 没有匹配的行。 "trick" 是在 WHERE 子句中使用谓词来过滤掉所有找到匹配的行,只留下没有匹配的行。
例如,要从 Documents
中检索在 Notes
中没有任何符合指定条件的匹配行的行:
SELECT d.*
FROM Documents d
LEFT
JOIN Notes n
ON n.docId = d.id
AND n.status IN (2,3)
WHERE n.docId IS NULL
(我猜测 docId
和 status
是对 Notes
中列的引用,而 id
是对 [=11 中列的引用=]。您的查询中的列引用没有限定,因此我们只能猜测哪些列在 table 中。最佳做法是在引用多个 table 的查询中限定所有列引用]。一个很大的好处是它可以在不查看 table 定义的情况下破译语句,找出哪些列来自哪些 table。)
该查询将从 Documents
中的 return 行,其中在 Notes 中没有任何 "matching" 状态为 2
或 3
的行.
因为 LEFT JOIN 是外连接,它 returns all 来自 Documents
的行,以及来自 Notes
的匹配行. Documents
中没有匹配行的任何行也将被 returned,Notes
中的列的值为 NULL。连接中的相等谓词 (n.docId = d.Id
) 向我们保证任何 "matching" 行都将具有 docId
.
的非 NULL 值
"trick" 是 WHERE
子句中的谓词:n.docId IS NULL
任何匹配的行都将被过滤掉,所以我们只剩下 Documents
中没有匹配的行。
原查询有status NOT IN (2,3)
。这基本上会忽略 Notes
中具有其中一种状态的行,并且只有具有其他非 NULL 状态值的行会 "match"。根据规范... "no notes with a status of 2 or 3",这似乎暗示您希望在查询中使用 status IN (2,3)
。
我有一个名为 Documents 的 table 和一个名为 Notes 的 table 用于存储文档的注释。我需要获取所有没有状态为 2 或 3 的注释的文档。
SELECT * FROM Documents
WHERE NOT EXISTS (
SELECT docID FROM Notes WHERE docId = id AND status IN (2, 3)
)
这非常慢,但可以。我尝试进行内部连接,但如果只有一张纸条的状态不是 2 或 3,它仍会显示文档。我需要它只显示在任何注释中都没有出现 2 或 3 的文档。
谁能帮忙!?谢谢!
一种方法:
SELECT *, COUNT(docID)
FROM Documents
LEFT JOIN Notes ON docID = id AND (status IN (2,3))
GROUP BY id
HAVING COUNT(docID) = 0
如果 status=2 或 status=3,则计数将为非零,并且 having
将完全消除文档。
反加入 是一种熟悉的 SQL 模式。
使用该模式,我们使用外连接操作 return 所有行,以及匹配的行,包括 没有匹配的行。 "trick" 是在 WHERE 子句中使用谓词来过滤掉所有找到匹配的行,只留下没有匹配的行。
例如,要从 Documents
中检索在 Notes
中没有任何符合指定条件的匹配行的行:
SELECT d.*
FROM Documents d
LEFT
JOIN Notes n
ON n.docId = d.id
AND n.status IN (2,3)
WHERE n.docId IS NULL
(我猜测 docId
和 status
是对 Notes
中列的引用,而 id
是对 [=11 中列的引用=]。您的查询中的列引用没有限定,因此我们只能猜测哪些列在 table 中。最佳做法是在引用多个 table 的查询中限定所有列引用]。一个很大的好处是它可以在不查看 table 定义的情况下破译语句,找出哪些列来自哪些 table。)
该查询将从 Documents
中的 return 行,其中在 Notes 中没有任何 "matching" 状态为 2
或 3
的行.
因为 LEFT JOIN 是外连接,它 returns all 来自 Documents
的行,以及来自 Notes
的匹配行. Documents
中没有匹配行的任何行也将被 returned,Notes
中的列的值为 NULL。连接中的相等谓词 (n.docId = d.Id
) 向我们保证任何 "matching" 行都将具有 docId
.
"trick" 是 WHERE
子句中的谓词:n.docId IS NULL
任何匹配的行都将被过滤掉,所以我们只剩下 Documents
中没有匹配的行。
原查询有status NOT IN (2,3)
。这基本上会忽略 Notes
中具有其中一种状态的行,并且只有具有其他非 NULL 状态值的行会 "match"。根据规范... "no notes with a status of 2 or 3",这似乎暗示您希望在查询中使用 status IN (2,3)
。