LEFT JOIN无法替换NOT EXISTS MYSQL

时间:2015-04-16 15:22:47

标签: mysql inner-join

我有一个名为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的文档。

任何人都可以帮忙!?谢谢!

2 个答案:

答案 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

(我猜测docIdstatus是对Notes中列的引用,而id是对{{1}中列的引用查询中的列引用不是合格的,因此我们可以猜测哪些列在哪个表中。最佳做法是限定引用多个表的查询中的所有列引用。一个很大的好处是它可以解密语句而不必查看表定义,找出哪些列来自哪个表。)

该查询将返回来自Documents的行,其中没有任何"匹配" Notes中的行,其状态为Documents2

因为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