我想我有你正在寻找的东西,但让我清楚地解释正在发生的事情。我仅从文件关系表中预查询(别名 PQ)每个文件 ID 的聚合。这些聚合基本上是 1 或 0 的标志,表明它有或没有。
左连接的结果,如果根本没有关系,你想要条目,所以你的 IS NULL 显然是好的。
现在,您需要考虑一个没有任何“TAG”或“CAT”条目的文件。这就是 HasOtherRelation 的 MAX( IF()) 出现的地方。通过给定文件 ID 的所有条目,我关心的是“除了 cat 或 tag 之外是否有任何条目”...如果是,则设置为 1 ,否则保留 0。类似地,“HasTagOrCat”的标志,所以在我的 where 子句中,我正在寻找任何具有其他关系 = 1 并且 Has Tag 或 Cat 标志为零的东西。
最后,满足您对 tag 或 cat 限定符的考虑的要求,但如果文件有其他 cat 或 tag 条目则不满足。类似的 MAX( IF()) 。
select
f.id,
f.file_title
from
files f
LEFT JOIN
( select
fr.file_id,
max( if( fr.relationship IN ('tag','cat'), 1, 0 )) as HasTagOrCat,
max( if( fr.relationship NOT IN ('tag','cat'), 1, 0 )) as HasOtherRelation,
max( if( fr.relationship = 'tag' AND fr.relationship_id IN('12','15'), 1, 0 )) as HasTags,
max( if( fr.relationship = 'cat' AND fr.relationship_id IN('1','2'), 1, 0 )) as HasCats,
max( if( fr.relationship = 'tag' AND fr.relationship_id NOT IN('12','15'), 1, 0 )) as HasOtherTags,
max( if( fr.relationship = 'cat' AND fr.relationship_id NOT IN('1','2'), 1, 0 )) as HasOtherCats
from
file_relationships AS fr
group by
fr.file_id ) PQ
ON f.id = PQ.file_id
where
PQ.file_id IS NULL
OR ( PQ.HasOtherRelation = 1
AND PQ.HasTagOrCat = 0 )
OR ( PQ.HasTags + PQ.HasCats > 0
AND PQ.HasOtherTags + PQ.HasOtherCats = 0 )
因此,在内部预查询结束时,您的结果将具有以下内容
File_ID HasTagOrCat HasOtherRelation HasTags HasCats HasOtherTags HasOtherCats
1 1 0 1 1 0 0
2 1 0 1 1 1 1
3 1 0 1 0 0 0
因此,您的数据在数据样本中没有任何此类非标签/猫考虑因素,对于关系表中没有此类文件条目也没有任何 NULL,但上面总结的其他数据将导致仅文件 1 和 3 包含在结果集...
他们每个人都至少有一个标签或猫,您正在寻找一个您不想要的其他标签/猫。对于条目 2,是的,它同时具有您正在寻找的标签和猫,但也有您没有的其他标签/猫,因此从结果中排除。