私はあなたが探しているものを持っていると思いますが、何が起こっているのかを明確に説明させてください. ファイル関係テーブルからのみ、各ファイル ID の集計を事前クエリ (エイリアス PQ) しています。これらの集計は基本的に、何かを持っているかどうかを示す 1 または 0 のフラグです。
左結合の結果、関係がまったくない場合はエントリが必要なので、 IS NULL は明らかに良いことです。
ここで、「TAG」または「CAT」エントリを持たないファイルを検討してください。これが、HasOtherRelation の MAX( IF()) の出番です。特定のファイル ID のすべてのエントリを通じて、私が気にするのは、「cat または tag 以外のエントリがあるか」ということだけです...そうであれば、1 に設定します、それ以外の場合は 0 のままにします。同様に「HasTagOrCat」のフラグなので、where 句で、他のリレーション = 1 かつ Has Tag Or Cat フラグが 0 であるすべてのものを探しています。
最後に、ファイルに他の cat または tag エントリが含まれている場合ではなく、tag または cat 修飾子に関する考慮事項を満たす要件について説明します。それらの同様の 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 については、はい、探していたタグと猫の両方がありましたが、他のタグ/猫も含まれていたため、結果から除外されました。