2010-07-16 37 views
18

Tôi đang cố truy vấn Đối tượng khớp với TẤT CẢ của một bộ Thẻ nhất định.Mysql tham gia truy vấn cho nhiều "thẻ" (mối quan hệ nhiều-nhiều) khớp với TẤT CẢ thẻ?

Về cơ bản, tôi muốn người dùng có thể thêm vào ngày càng nhiều Thẻ để lọc hoặc "thu hẹp" kết quả tìm kiếm của họ, giống như newegg.com.

Cấu trúc bảng của tôi là một bảng các đối tượng, một bảng các thẻ và một MANY: MANY bảng quan hệ ObjectsTags. Vì vậy, tôi có lệnh JOIN truy vấn như vậy:

SELECT * FROM Objects 
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id) 
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id) 

tôi đã cố gắng sử dụng một khoản IN/điều kiện, như thế này:

SELECT * FROM Objects 
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id) 
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id) 
WHERE Tags.name IN ('tag1','tag2') 
GROUP BY Objects.id 

Nhưng tôi học được rằng điều này mô phỏng một loạt các ORS, vì vậy nhiều thẻ bạn thêm vào truy vấn các kết quả MORE bạn nhận được, thay vì tập hợp kết quả thu hẹp như tôi đã hy vọng.

Tôi cũng đã cố gắng làm nhiều như nơi điều kiện, ANDed với nhau:

SELECT * FROM Objects 
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id) 
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id) 
WHERE Tags.name LIKE 'tag1' 
AND Tags.name LIKE 'tag2' 
GROUP BY Objects.id 

Nhưng điều này không có kết quả trả về, kể từ khi kết quả được nhóm lại với nhau bên ngoài tham gia Tags.name cột chỉ chứa 'TAG1', và cũng không phải 'tag2'. Hàng kết quả trong đó 'tag2' trùng khớp được "ẩn" bởi Nhóm.

Làm cách nào để tôi có thể đối sánh TẤT CẢ các thẻ để có được hiệu ứng "thu hẹp" hoặc "khoan xuống" mà tôi theo sau? Cảm ơn.

Trả lời

26

Sử dụng:

SELECT * 
    FROM OBJECTS o 
    JOIN OBJECTSTAGS ot ON ot.object_id = o.id 
    JOIN TAGS t ON t.id = ot.tag_id 
    WHERE t.name IN ('tag1','tag2') 
GROUP BY o.id 
    HAVING COUNT(DISTINCT t.name) = 2 

Bạn bị mất tích mệnh đề HAVING.

Không cần phải LEFT JOIN nếu bạn chỉ muốn các hàng có cả hai thẻ tồn tại.

+1

DISTINCT là cần thiết nếu bạn không có khóa chính hoặc ràng buộc/chỉ mục duy nhất trên cặp cột trong OBJECTTAGS để đảm bảo không có trùng lặp (đây sẽ là các kết quả sai). –

+0

hoạt động tuyệt vời! cảm ơn! không bao giờ nghĩ đến việc sử dụng HAVING theo cách đó với số lượng hàng. FYI cho những người khác: Tôi đang xây dựng truy vấn của mình bằng PHP để mệnh đề HAVING khớp với số lượng thẻ tôi đang tìm kiếm, vì vậy nếu nó là ('tag1', 'tag2', 'tag3') Tôi đang tìm HAVING COUNT (DISTINCT t.name) = 3, để đảm bảo kết quả có TẤT CẢ các thẻ. – thaddeusmt

+0

Câu trả lời thú vị. Cảm ơn ! –

Các vấn đề liên quan