我有一个名为Documents的表和一个名为Notes的表,用于存储Documents的注释。我需要获取所有没有状态为2或3的笔记的文档。
SELECT * FROM Documents
WHERE NOT EXISTS (
SELECT docID FROM Notes WHERE docId = id AND status IN (2, 3)
)
这非常慢,但确实有效。我尝试进行内连接,但如果只有一个音符的状态不是2或3,它仍会显示文档。我需要它只显示任何笔记中没有出现2或3的文档。
任何人都可以帮忙!?谢谢!
答案 0 :(得分:1)
一种方法:
SELECT *, COUNT(docID)
FROM Documents
LEFT JOIN Notes ON docID = id AND (status IN (2,3))
GROUP BY id
HAVING COUNT(docID) = 0
如果状态= 2或状态= 3,则计数将为非零,having
将完全取消该文档。
答案 1 :(得分:0)
反连接是一种熟悉的SQL模式。
使用该模式,我们使用外部联接操作返回所有行以及匹配的行,包括不匹配的行。 "技巧"是在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
是对{{1}中列的引用查询中的列引用不是合格的,因此我们可以猜测哪些列在哪个表中。最佳做法是限定引用多个表的查询中的所有列引用。一个很大的好处是它可以解密语句而不必查看表定义,找出哪些列来自哪个表。)
该查询将返回来自Documents
的行,其中没有任何"匹配" Notes中的行,其状态为Documents
或2
。
因为LEFT JOIN是外部联接,所以它返回{em>所有行3
以及来自Documents
的匹配行。来自Notes
但没有匹配行的任何行也将被返回,Documents
列的NULL值为NULL。连接中的等式谓词(Notes
)保证了任何"匹配"对于n.docId = d.Id
,行将具有非NULL值。
"技巧"是docId
子句中的谓词:WHERE
任何匹配的行都会被过滤掉,因此我们会留下n.docId IS NULL
中没有匹配的行。
原始查询有 Documents
。这基本上会忽略具有这些状态之一的status NOT IN (2,3)
中的行,并且只有具有其他非NULL值状态的行将匹配"。根据规范......"没有状态为2或3"的注释,这似乎暗示您在查询中需要Notes
。