Sử dụng 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)
Sử dụng 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
Sử dụng 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)
Giải thích
Điểm mấu chốt của mọi thứ là COUNT(DISTINCT t.name)
cần phải khớp với số lượng tên thẻ để đảm bảo rằng tất cả các thẻ đó đều liên quan đến bài đăng. Nếu không có DISTINCT, có nguy cơ trùng lặp của một trong các tên có thể trả về số lượng là 7 - vì vậy bạn sẽ có một dương tính giả.
Hiệu suất
Hầu hết sẽ cho bạn biết JOIN là tối ưu, nhưng các JOIN cũng có nguy cơ trùng lặp các hàng trong tập kết quả. EXISTS sẽ là lựa chọn tiếp theo của tôi - không có rủi ro trùng lặp và thực thi thường nhanh hơn nhưng việc kiểm tra kế hoạch giải thích cuối cùng sẽ cho bạn biết điều gì tốt nhất dựa trên thiết lập và dữ liệu của bạn.