[RESOLU] Requête plusieurs valeurs pour un ID

Eléphant du PHP | 190 Messages

26 juil. 2012, 14:54

Bonjour,

j'ai 3 tables

img(id,url)
tags(id,name)
img_has_tag(id_img,id_tag)

vous l'aurez compris, ma table img_has_tag et une table de liaison qui contient tout les tags pour chaque image.

j'arrive à récupérer toutes les images liées à un seul tag mais je bloque lorsque je veux récupérer les images liées à plusieurs tags...

Exemple

3 images

id=1
id=2
id=3

3 tags

id=11
id=12
id=13

donc ma table img_has_tag ressemble a ceci

id_img | id_tag

1 | 11
1 | 13
2 | 11
2 | 12
2 | 13
3 | 12
3 | 13

Donc pas de problèmes pour récupérer l'id des image liée à un seul tag:
SELECT id,url FROM img WHERE id IN(SELECT id_img FROM img_has_tag WHERE id_tag=12)
mais si par exemple je veux récupérer toutes les images qui sont taguées 12 ET 13 par exemple ? Donc obligatoirement les deux pas l'un ou l'autre.

Auriez vous une piste ?

Eléphant du PHP | 53 Messages

26 juil. 2012, 15:08

Bonjour,

Heu petite question pourquoi une requête imbriquée lorsque une simple liaison suffit ?
Tu peut utiliser "IN" et un tableau de valeur.
SELECT i.id, i.url 
FROM img AS i , img_has_tag AS t
WHERE i.id = t.id_img
AND t.id_tag IN (12,13);
Cordialement.
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison.

Eléphant du PHP | 190 Messages

26 juil. 2012, 15:25

Merci pour ta réponse,

effectivement pour la liaison, je vais modifier cela.

Par contre ta solution (que j'avais déjà testée) me renvoie aussi les ids qui ne contiennent qu'un seul des deux tags, alors que je veux récupérer strictement les id des images qui contiennent les deux tags. C'est bien la que je coince.

Eléphant du PHP | 53 Messages

26 juil. 2012, 15:38

Bonjour,

Ha je n'avais pas compris cela, on change de requête alors :
SELECT i.id, i.url
FROM img AS i , img_has_tag AS t
WHERE i.id = t.id_img
AND t.id_tag = 12 ;
AND i.id IN ( SELECT id_img 
                   FROM img_has_tag
                   WHERE id_tag = 13 );
Par contre je ne suis pas sur que ma requête soi optimisée : je ne me rappel plus s'il y une solution plus simple pour une condition tel que ça.

Une idée :
SELECT i.id, i.url
FROM img AS i , img_has_tag AS t
WHERE i.id = t.id_img
GROUP BY i.id
HAVING (t.id_tag = 12 AND t.id_tag = 13);
Pour celle çi c'est à tester je ne suis pas sur que cela marche.

Cordialement.
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison.

Eléphant du PHP | 190 Messages

26 juil. 2012, 15:58

Effectivement la deuxième ne fonctionne pas. "Unknown column 'img_has_tag.id_tag' in 'having clause'"

Je vais encore chercher pour trouver une solution plus optimisée car même si dans mon exemple il n'y a que deux tags à tester, mon appli peut envoyer des requêtes avec des dizaines de tags (système de recherche personnalisée), je me retrouverai donc avec des dizaines de requête imbriquées.

Je pense qu'une jointure serait la solution mais je n'arrive pas à construire ma requête.

Merci

Eléphant du PHP | 53 Messages

26 juil. 2012, 16:22

Rebonjour,

Je ne me suis pas suffisamment entrainé avec les 'UNION' pour t'aider, désolé.

Cordialement.
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison.

Eléphant du PHP | 190 Messages

26 juil. 2012, 17:23

J'ai trouvé,

je postes la réponse, ça peut servir. Et si quelqu'un trouve plus simple qu'il me le dise.
SELECT i.id,i.url,t.id_tag
FROM img AS i
INNER JOIN img_has_tag AS t ON i.id = t.id_img
WHERE t.id_tag IN(12,13,25,34)
GROUP BY i.id
HAVING COUNT(DISTINCT t.id_tag) = 4
La clause IN change en fonction du nombre de tags ainsi que la clause HAVING (ici =4 puisque 4 tags).

Merci à toi qui m'a mis sur la piste du HAVING ;)

Edit: le distinct n'est pas utile si il n'y a pas de possibilité de doubles dans la paire (id_img,id_tag) ce qui est mon cas.