对不起问题标题..我不知道如何以更清晰的方式写下来。
所以,我有这些表:
tracks
,包含id
(曲目ID)& name
(曲目名称)tags
,包含id
(标记ID)& name
(标记名称)track_tags
,包含track_id
& tag_id
我必须在列表中找到所有包含所有标签的曲目(例如我需要找到所有曲目,一次都有'摇滚','pop'和'dance'标签。)
之前,我已经解决了类似的问题,但找到了至少有1个标记匹配的所有曲目。这很容易:
SELECT tracks.*
FROM tags
INNER JOIN track_tags ON tags.id = track_tags.tag_id
INNER JOIN tracks ON track_tags.track_id = tracks.id
WHERE tags.name IN('pop', 'rock', 'dance')
GROUP BY tracks.id
但我完全不知道如何找到所有与列表中的所有标签完全匹配的曲目。
我考虑过检索所有曲目及其所有标签到我的应用程序并过滤那里的曲目 - 但是它们中有很多(数十万),app也使用分页,可以使用LIMIT在上层轻松实现查询。
也许可以用另一种方式,使用mysql功能?我真的觉得用所有标签选择所有曲目并在应用端过滤它们会导致网络服务器崩溃。
答案 0 :(得分:2)
解决此问题的最常用方法是使用带有having
子句的聚合:
SELECT tracks.*
FROM tags INNER JOIN
track_tags
ON tags.id = track_tags.tag_id INNER JOIN
tracks
ON track_tags.track_id = tracks.id
GROUP BY tracks.id
HAVING sum(tags.name = 'pop') > 0 and
sum(tags.name = 'rock') > 0 and
sum(tags.name = 'dance') > 0;
稍微有点变化是在where中进行过滤,然后查找三个不同的标记:
SELECT tracks.*
FROM tags INNER JOIN
track_tags
ON tags.id = track_tags.tag_id INNER JOIN
tracks
ON track_tags.track_id = tracks.id
WHERE tags.name IN('pop', 'rock', 'dance')
GROUP BY tracks.id
HAVING count(distinct tags.name) = 3;