Je crée un moteur de recherche de chansons à l'aide de balises et j'ai du mal à créer la requête SQL qui répertorie toutes les chansons qui correspondent aux balises.

La base de données ressemble à ceci: http://i.imgur.com/5zmfAz8.png

Les morceaux ont de nombreux tags via une table intermédiaire (SongTags).

Prenons une population comme exemple:

Tags : Electro, Instrumental, Energétique, Mélancolique, Vocal, Rock

Chansons : SongA (électro, mélancolique, vocal) Chansons (instrumentales, mélancoliques, rock) Chansons (énergiques, vocales)


La recherche doit renvoyer les chansons contenant TOUTES les balises demandées.

Recherche1:

"Vocal" renvoie: SongS, SongS

Recherche2:

"Vocal", "Energetic" revient: SongC

Recherche3:

"Vocal", "Energetic", "Electro" revient: rien


Je vois comment faire une recherche sur 1 balise, mais pas sur plusieurs balises. Par exemple pour le Search1, je sais que cela fonctionnerait:

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'

Mais ensuite, je n'ai aucune idée de la façon dont je pourrais exécuter Search2, car j'ai besoin que le morceau contienne à la fois "Vocal" et "Energetic".

Éditer:

J'utilise PostgreSQL

0
Leoss 23 déc. 2015 à 00:59

2 réponses

Meilleure réponse
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
0
archana 22 déc. 2015 à 22:12

Si vous voulez obtenir des chansons qui correspondent à toutes les balises qui vous sont fournies, j'utiliserais des sous-sélections. Ils seront un peu lents, mais cela vous donnera une solution complète:

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')

Si votre serveur SQL prend en charge la commande INTERSECT, vous pouvez le faire:

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')

Ce qui, je pense, est une façon plus cool de le faire.

J'espère que cela pourra aider. :)

0
Pól 22 déc. 2015 à 22:29