在MySQL数据库中,我具有三个连接的表:文本链接到版本,该链接链接到中间表 editor_attestations (我认为第四表编辑器与此处无关)。通常每个文本都有多个版本,而每个版本又通常具有几个editor_attestations(通过联合出版)。
如果我想使用特定的编辑器获取所有文本和版本,则可以正常工作:
SELECT texts.text_id FROM texts
LEFT JOIN editions ON texts.text_id = editions.text_id
LEFT JOIN editor_attestations ON editions.edition_id = editor_attestations.edition_id
WHERE editor_attestations.editor_id = 102
现在,我尝试了几种方法,以使所有文本均未由editor_id = 102编辑,但似乎没有任何作用。
SELECT texts.text_id FROM texts
LEFT JOIN editions ON texts.text_id = editions.text_id
LEFT JOIN editor_attestations ON editions.edition_id = editor_attestations.edition_id
WHERE (editor_attestations.editor_id != 102 or editor_attestations.editor_id is null)
在结果中有许多记录,其中editor_id 102与其他人合作,因此editor_attestations.editor_id!= 102成立。但是我想排除那些。
我只想在表1(文本)中包含与表3(editor_attestations)中的特定值没有任何联系的值。
我尝试对子查询使用NOT IN或NOT EXISTS,但这不起作用。
我觉得它不应该那么复杂...
答案 0 :(得分:1)
由于只需要texts.text_id
,因此可以按texts.text_id
分组并在HAVING子句中设置条件。
SELECT texts.text_id
FROM texts
LEFT JOIN editions ON texts.text_id = editions.text_id
LEFT JOIN editor_attestations ON editions.edition_id = editor_attestations.edition_id
GROUP BY texts.text_id
HAVING SUM(editor_attestations.editor_id = 102) = 0
答案 1 :(得分:1)
forpas和xavier的答案证明了可行的方法。
作为使用NOT EXISTS
SELECT t.text_id
FROM texts t
WHERE NOT EXISTS ( SELECT 1
FROM editions e
JOIN editor_attestations a
ON a.edition_id = e.edition_id
WHERE a.editor_id = 102
AND e.text_id = t.text_id
)
请注意子查询e.text_id = t.text_id
中的谓词,该谓词将子查询与外部查询相关联。
此方法允许返回texts
中的其他列,而不会重复使用JOIN操作可能会发生的行。
对于大型集合,需要合适的索引以实现最佳性能。
另一种替代方法是使用反联接模式:
SELECT t.text_id
FROM texts t
-- match to editor_id=102
LEFT
JOIN ( SELECT e.text_id
FROM editions e
JOIN editor_attestations a
ON a.edition_id = e.edition_id
WHERE a.editor_id = 102
GROUP BY e.text_id
) s
ON s.text_id = t.text_id
-- exclude rows that had a match
WHERE s.text_id IS NULL
内联视图查询s
为我们提供了与text_id
相关的editor_id=102
的独特列表。反联接是此查询的返回的左外部联接,因此它将返回所有行文本以及来自s
的匹配行。诀窍是WHERE子句中的一个条件,该条件排除具有匹配项的行(如果s
中有匹配的行,我们保证s.text_id
将为非空,因为只有非空值可以满足联接条件(ON s.text_id =
中的相等比较。如果排除那些行,则剩下texts
中的行,它们 not 中没有匹配的行s
。
答案 2 :(得分:0)
一个非常简单的解决方案是:我寻找由某个编辑器修改过的所有文本,然后选择互补的文本集。可能效率不高,但是对于小型数据库而言,它会起作用:
SELECT texts.text_id FROM texts where texts.text_id NOT IN
(SELECT editions.text_id FROM editions
JOIN editor_attestations ON editions.edition_id = editor_attestations.edition_id
WHERE editor_attestations.editor_id = 102
)