INの使用:
SELECT p.*
FROM POSTS p
WHERE p.id IN (SELECT tg.post_id
FROM TAGGINGS tg
JOIN TAGS t ON t.id = tg.tag_id
WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art')
GROUP BY tg.post_id
HAVING COUNT(DISTINCT t.name) = 7)
JOINの使用
SELECT p.*
FROM POSTS p
JOIN (SELECT tg.post_id
FROM TAGGINGS tg
JOIN TAGS t ON t.id = tg.tag_id
WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art')
GROUP BY tg.post_id
HAVING COUNT(DISTINCT t.name) = 7) x ON x.post_id = p.id
EXISTSの使用
SELECT p.*
FROM POSTS p
WHERE EXISTS (SELECT NULL
FROM TAGGINGS tg
JOIN TAGS t ON t.id = tg.tag_id
WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art')
AND tg.post_id = p.id
GROUP BY tg.post_id
HAVING COUNT(DISTINCT t.name) = 7)
説明
重要なのは、COUNT(DISTINCT t.name)
これらすべてのタグが投稿に関連していることを確認するには、タグ名の数と一致させる必要があります。 DISTINCTがないと、名前の1つが重複すると、カウントが7になる可能性があるため、誤検知が発生する可能性があります。
パフォーマンス
ほとんどの場合、JOINが最適であると言われますが、JOINは結果セットの行を複製するリスクもあります。 EXISTSが私の次の選択肢です。重複するリスクはなく、一般的に実行は高速ですが、Explain Planを確認することで、最終的にはセットアップとデータに基づいて何が最善かがわかります。