Précédent   Forum des professionnels en informatique > Bases de données > MySQL > Requêtes
Requêtes Forum d'entraide sur les requêtes MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 20/12/2010, 20h44   #1
Invité de passage
 
Inscription : mars 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 9
Points : 3
Points : 3
Par défaut Un coup de main pour une requête ?

Bonjour,

J'ai un problème qui me semble très simple mais après avoir peiné dessus une partie de la journée, je ne trouve pas ....

J'ai une table Article liée via une table de jointure ArticleTag à une table Tag.

Article (id, titre, contenu, ...)
(1, Le vol des mouettes, blablabla)
(2, La chouette huppée, bliblibli)

ArticleTag (article_id, tag_id)
(1, 1)
(1, 2)
(2, 1)
(2, 3)

Tag (id, nom)
(1, Oiseaux)
(2, Documentaire)
(3, Glace à la vanille)

L'idée de la requête est de pouvoir filtrer les articles par autant de tags que nécessaire.

Exemples :
En filtrant avec "Oiseaux" et "Documentaire" je ne devrais récupérer que l'article 1.
En filtrant uniquement avec "Oiseaux" je récupère les deux articles.

Bref je ne comprend pas, ça me semble relativement simple mais je ne vois pas.

En espérant que quelqu'un saura me sortir de là, en tout cas merci à ceux qui essaieront.
kibla est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2010, 21h09   #2
Membre Expert
 
Avatar de Madfrix
 
Inscription : juin 2007
Messages : 2 278
Détails du profil
Informations personnelles :
Localisation : France, Gironde (Aquitaine)

Informations forums :
Inscription : juin 2007
Messages : 2 278
Points : 2 324
Points : 2 324
Bonjour, tu dois faire cette requete avec NOT EXISTS.

Regarde les exemples ici notamment le dernier
Madfrix est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2010, 21h53   #3
Invité de passage
 
Inscription : mars 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 9
Points : 3
Points : 3
Bonjour,

Merci pour ta réponse, j'ai donc essayé avec le mot clé "EXISTS"
Code :
1
2
3
4
5
 
SELECT * FROM Article WHERE NOT EXISTS
   (SELECT * FROM Tag WHERE NOT EXISTS
       (SELECT * FROM `ArticleTag` WHERE tag_id IN (1,2))
   )
Visiblement cela ne fonctionne pas, d'ailleurs j'ai du mal à comprendre comment ça pourrait fonctionner, "EXISTS" permet de tester si une requête renvoie ou non des enregistrements. Je ne vois donc pas comment ça pourrait filtrer mes articles.

Ai-je fait quelque chose de travers ?

En y réfléchissant à tête reposé, j'ai trouvé une solution, mais elle me parait un peu lourde, en effet si j'ai 50 tags sur lesquels filtrer ça fait 50 sous-requetes...
Code :
1
2
3
4
 
SELECT * FROM Article WHERE 
Article.id IN (SELECT article_id FROM ArticleTag WHERE tag_id = 1)
AND Article.id IN (SELECT article_id FROM ArticleTag WHERE tag_id = 2)
Si quelqu'un a mieux en stock.

Merci !
kibla est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2010, 22h04   #4
Membre Expert
 
Avatar de Madfrix
 
Inscription : juin 2007
Messages : 2 278
Détails du profil
Informations personnelles :
Localisation : France, Gironde (Aquitaine)

Informations forums :
Inscription : juin 2007
Messages : 2 278
Points : 2 324
Points : 2 324
Citation:
Envoyé par kibla Voir le message
"EXISTS" permet de tester si une requête renvoie ou non des enregistrements. Je ne vois donc pas comment ça pourrait filtrer mes articles.
Il faut justement que tu regardes si cela renvoie ou non des enregistrements concernant un sous ensemble. Par exemple si tu ne retourne pas d'enregistrements avec NOT EXISTS dans un sous ensemble comprenant l'ensemble de tes Articles.id par exemple, alors ce sous ensemble contient l'ensemble de tes id. C'est mal expliqué mais c'est à quelque chose près ce que tu veux faire.

Sinon en moins propre tu peux faire un COUNT associé à un HAVING pour ta requete
Madfrix est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2010, 22h44   #5
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 977
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 10 977
Points : 18 221
Points : 18 221
Envoyer un message via MSN à CinePhil
Au contraire Madfrix, je pense que la bonne manière de faire est justement de compter le nombre de lignes et de le comparer au nombre d'éléments du filtre.
Citation:
En filtrant avec "Oiseaux" et "Documentaire" je ne devrais récupérer que l'article 1.
Code :
1
2
3
4
5
6
SELECT at.article_id
FROM ArticleTag at
  INNER JOIN Tag t ON t.id = at.tag_id
WHERE t.nom IN ('Oiseaux', 'Documentaire')
GROUP BY at.article_id
HAVING COUNT(*) = 2
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2010, 23h03   #6
Membre Expert
 
Avatar de Madfrix
 
Inscription : juin 2007
Messages : 2 278
Détails du profil
Informations personnelles :
Localisation : France, Gironde (Aquitaine)

Informations forums :
Inscription : juin 2007
Messages : 2 278
Points : 2 324
Points : 2 324
Je partais du principe que ca fait 1 calcul dynamique à faire en plus pour calculer le "2" du HAVING

Après, niveau temps d'éxécution en fonction de la volumétrie j'en sais rien...

Sur quelques lignes, c'est vrai que ca va pas changer grand chose c'est sur
Madfrix est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2010, 13h25   #7
Invité de passage
 
Inscription : mars 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 9
Points : 3
Points : 3
Bon la requête de cinephil fonctionne, je ne dirais pas que je comprend pourquoi, mais je vais essayer en tout cas.
Merci à vous deux !
kibla est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2010, 13h43   #8
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 977
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 10 977
Points : 18 221
Points : 18 221
Envoyer un message via MSN à CinePhil
Citation:
Envoyé par kibla Voir le message
Bon la requête de cinephil fonctionne, je ne dirais pas que je comprend pourquoi,
La jointure entre les deux tables fera que si un article est lié aux deux tags 'Oiseaux', et 'Documentaire', il y aura deux lignes de résultat.
On groupe par article et on vérifie qu'effectivement le comptage des lignes pour chaque article est bien égal au nombre de noms dans le IN. HAVING ne retient que les articles qui satisfont cette condition sur le comptage.

Il te suffit de paramétrer ta requête en changeant le nombre requis pour le COUNT(*) en fonction du nombre d'éléments dans le IN.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 06h11.


 
 
 
 
Partenaires

Hébergement Web