查询以搜索包含所有请求标签的歌曲



我正在使用标签为歌曲创建搜索引擎,并且在构建SQL查询时遇到了问题,该查询将列出所有与标签匹配的歌曲。

数据库如下所示:https://i.stack.imgur.com/O0Tuo.png

歌曲通过一个中间表(SongTags)有许多标签。

让我们以人口为例:

标签:电子、器乐、活力、忧郁、声乐、摇滚

歌曲:SongA(电子、忧郁、声乐)歌曲B(器乐、忧郁、摇滚)歌曲C(充满活力,声乐)


搜索应该返回包含所有请求标签的歌曲。

搜索1:

"Vocal"返回:SongA,SongB

搜索2:

"Vocal","Energetic"回归:SongC

搜索3:

"Vocal"、"Energetic"、"Electro"返回:无


我知道如何在一个标签上进行搜索,但不在多个标签上。以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"one_answers"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 server支持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')

我认为这是一种更酷的方式。

希望能有所帮助。:)

最新更新