查询以搜索包含所有请求标签的歌曲
Query to search for the songs to contain all the requested tags
我正在为使用标签的歌曲创建一个搜索引擎,但我在构建 SQL 查询以列出所有与标签匹配的歌曲时遇到了问题。
数据库如下所示:
http://i.imgur.com/5zmfAz8.png
歌曲通过中间层有很多标签table(SongTags)。
让我们以人口为例:
标签:
电子、器乐、活力、忧郁、声乐、摇滚
歌曲:
SongA(电子、忧郁、声乐)
SongB(器乐、忧郁、摇滚)
SongC(精力充沛,声乐)
搜索应该 return 包含请求的所有标签的歌曲。
搜索 1:
"Vocal" returns: 歌曲A, 歌曲B
搜索 2:
"Vocal", "Energetic" returns:宋C
搜索 3:
"Vocal", "Energetic", "Electro" returns: 无
我知道如何搜索 1 个标签,而不是多个标签。
例如 Search1,我知道这会起作用:
SELECT * FROM "songs"
INNER JOIN "song_tags" ON "song_tags"."song_id" = "songs"."id"
INNER JOIN "tags" ON "tags"."id" = "song_tags"."tag_id"
WHERE "tags"."name" = 'Vocal'
但是我不知道如何执行 Search2,因为我需要歌曲同时包含 "Vocal" 和 "Energetic"。
编辑:
我正在使用 PostgreSQL
SELECT songs.*, COUNT(songs.id) AS total FROM "songs"
INNER JOIN "song_tags" ON "song_tags"."song_id" = "songs"."id"
INNER JOIN "tags" ON "tags"."id" = "song_tags"."tag_id"
WHERE "tags"."name" IN ('Vocal', 'Energetic')
GROUP BY songs.id
HAVING total = 2
如果您想获得与所有 标签匹配的歌曲,我会使用子选择。它们会有点慢,但它会给你一个百搭的解决方案:
SELECT songs.* FROM songs
WHERE songs.song_id IN
(SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'VOCAL')
AND songs.song_id IN (SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'ENERGETIC')
如果您的 SQL 服务器支持 INTERSECT 命令,您可以这样做:
SELECT songs.* FROM songs
WHERE songs.song_id IN
(SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'VOCAL'
INTERSECT
SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'ENERGETIC')
我认为这是一种更酷的方式。
希望对您有所帮助。 :)
我正在为使用标签的歌曲创建一个搜索引擎,但我在构建 SQL 查询以列出所有与标签匹配的歌曲时遇到了问题。
数据库如下所示: http://i.imgur.com/5zmfAz8.png
歌曲通过中间层有很多标签table(SongTags)。
让我们以人口为例:
标签: 电子、器乐、活力、忧郁、声乐、摇滚
歌曲: SongA(电子、忧郁、声乐) SongB(器乐、忧郁、摇滚) SongC(精力充沛,声乐)
搜索应该 return 包含请求的所有标签的歌曲。
搜索 1:
"Vocal" returns: 歌曲A, 歌曲B
搜索 2:
"Vocal", "Energetic" returns:宋C
搜索 3:
"Vocal", "Energetic", "Electro" returns: 无
我知道如何搜索 1 个标签,而不是多个标签。 例如 Search1,我知道这会起作用:
SELECT * FROM "songs"
INNER JOIN "song_tags" ON "song_tags"."song_id" = "songs"."id"
INNER JOIN "tags" ON "tags"."id" = "song_tags"."tag_id"
WHERE "tags"."name" = 'Vocal'
但是我不知道如何执行 Search2,因为我需要歌曲同时包含 "Vocal" 和 "Energetic"。
编辑:
我正在使用 PostgreSQL
SELECT songs.*, COUNT(songs.id) AS total FROM "songs"
INNER JOIN "song_tags" ON "song_tags"."song_id" = "songs"."id"
INNER JOIN "tags" ON "tags"."id" = "song_tags"."tag_id"
WHERE "tags"."name" IN ('Vocal', 'Energetic')
GROUP BY songs.id
HAVING total = 2
如果您想获得与所有 标签匹配的歌曲,我会使用子选择。它们会有点慢,但它会给你一个百搭的解决方案:
SELECT songs.* FROM songs
WHERE songs.song_id IN
(SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'VOCAL')
AND songs.song_id IN (SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'ENERGETIC')
如果您的 SQL 服务器支持 INTERSECT 命令,您可以这样做:
SELECT songs.* FROM songs
WHERE songs.song_id IN
(SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'VOCAL'
INTERSECT
SELECT song_tags.song_id FROM song_tags st JOIN tags t ON st.tag_id = t.id AND t.name = 'ENERGETIC')
我认为这是一种更酷的方式。
希望对您有所帮助。 :)