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 28/06/2011, 02h00   #1
Invité de passage
 
Inscription : novembre 2006
Messages : 10
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 10
Points : 1
Points : 1
Par défaut Recherche avec critères sur plusieurs lignes

Bonjour,

Je n'arrive pas à faire une recherche sur une table dont voici la structure et 3 lignes :



Je voudrais que la requête suivante me retourne la valeur produit = 2 :

Code :
SELECT produit FROM `catalogue_produit_specificite` WHERE (specificite=1 AND valeur=2) AND (specificite=2 AND valeur=3)
(car le produit 2 a pour couple de spécificité/valeur 1,2 et 2,3)

Or... aucun résultat.

Je crois comprendre pourquoi, mais je ne vois pas comment résoudre mon problème.

Quelqu'un saurait m'aider ?

Merci d'avance
affro-jojo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 06h22   #2
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

Informations professionnelles :
Activité : Retraité
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
Saluton,
Il te faut mettre la table en jointure avec elle-même, faire un regroupement par produit, compter les lignes qui participent de la jointure et ne retenir que les regroupements dont l'effectif est égal à 2
Code sql :
1
2
3
4
5
6
7
8
SELECT c1.produit
FROM `catalogue_produit_specificite` AS c1
INNER JOIN `catalogue_produit_specificite` AS c2
ON c2.produit=c1.produit
AND c2.specificite IN (1,2)
AND c2.valeur IN (2,3)
GROUP BY c1.produit
HAVING COUNT(*) = 2
Attention toutefois, ce qui est sous-entendu dans cette requête c'est l'UNICITÉ des trios {produit, specificite, valeur} dans la table.
Si ce n'était pas le cas il faudrait remplacer
Code :
INNER JOIN `catalogue_produit_specificite` AS c2
par
Code :
INNER JOIN (SELECT DISTINCT produit, specificite, valeur FROM`catalogue_produit_specificite`) AS c2
__________________
Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
articles : Comment émuler un tableau croisé [quasi] dynamique
et : Une énigme mathématique résolue avec MySQL
recommande l'utilisation de PDO (PHP5 Data Objects)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 13h06   #3
Membre Expert
 
Inscription : août 2002
Messages : 1 036
Détails du profil
Informations forums :
Inscription : août 2002
Messages : 1 036
Points : 1 166
Points : 1 166
Bonjour,

J'ai essayé ta requête avec tes données. Celle-ci me retourne bien le produit 2.
J'ai ajouté une ligne : 3,1,2. Cette même requête retourne les produits 2 et 3.

Donc, à moins que je n'ai pas compris le problème, je ne vois pas où il y en a un.
jeca est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 13h30   #4
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

Informations professionnelles :
Activité : Retraité
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
Vu que la jointure se fait, principalement, sur l'identifiant produit, je ne vois pas comment le count(*) pourrait retourner autre chose que 1 alors qu'il n'y a qu'une ligne dans la table avec l'identifiant produit = 3.
Soit c'est la requête qui a été modifiée, soit il y a autre chose dans la table.

Par contre je me rends compte que si les lignes 2,1,2 et 2,2,3 étaient 2,2,2 et 2,1,3 la requête retournerait bien 2.
Ce n'est peut-être pas grave, mais il vaut mieux le préciser.
__________________
Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
articles : Comment émuler un tableau croisé [quasi] dynamique
et : Une énigme mathématique résolue avec MySQL
recommande l'utilisation de PDO (PHP5 Data Objects)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 13h49   #5
Membre Expert
 
Inscription : août 2002
Messages : 1 036
Détails du profil
Informations forums :
Inscription : août 2002
Messages : 1 036
Points : 1 166
Points : 1 166
Maljuna Kris => Désolé, j'ai été un peu vite : je n'ai pas vu la barre de scroll sous la requête, et la deuxième condition est masquée.

Et comme ça :
Code :
1
2
3
4
5
SELECT a.produit 
FROM catalogue_produit_specificite a
JOIN catalogue_produit_specificite b ON a.produit = b.produit
WHERE (a.specificite=1 AND a.valeur=2) 
AND (b.specificite=2 AND b.valeur=3)
jeca est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 14h24   #6
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

Informations professionnelles :
Activité : Retraité
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
Tu dois gagner sur le GROUP BY et le COUNT, par contre il faut ajouter DISTINCT dans le SELECT sinon, évidemment, tu auras des doublons.
Et ma mise ne garde afférente à l'unicité du trio {produit, specificite, valeur} reste valable.
__________________
Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
articles : Comment émuler un tableau croisé [quasi] dynamique
et : Une énigme mathématique résolue avec MySQL
recommande l'utilisation de PDO (PHP5 Data Objects)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 14h54   #7
Membre Expert
 
Inscription : août 2002
Messages : 1 036
Détails du profil
Informations forums :
Inscription : août 2002
Messages : 1 036
Points : 1 166
Points : 1 166
Citation:
Envoyé par Maljuna Kris Voir le message
Til faut ajouter DISTINCT dans le SELECT sinon, évidemment, tu auras des doublons.
Il ne peut y avoir de doublons que si deux lignes ont des valeurs identiques dans les trois colonnes.

Citation:
1 1 1
2 1 2
2 2 3
Sur ce contenu, la clause DISTINCT ne se justifie pas car la requête ne retourne qu'une ligne :
Citation:
2
Citation:
1 1 1
2 1 2
2 2 3
2 1 2
Sur celui-ci la clause DISTINCT se justifie, car elle retourne 2 lignes
Citation:
2
2
Donc le tout est de savoir si plusieurs lignes identiques peuvent exister.
jeca est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 15h18   #8
Expert Confirmé
 
Avatar de Maljuna Kris
 
Homme Avcxjo MoKo
Retraité
Inscription : novembre 2005
Messages : 2 530
Détails du profil
Informations personnelles :
Nom : Homme Avcxjo MoKo
Âge : 60

Informations professionnelles :
Activité : Retraité
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : novembre 2005
Messages : 2 530
Points : 3 523
Points : 3 523
Voui, au temps pour moi, j'avais gardé la logique du IN.
__________________
Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
articles : Comment émuler un tableau croisé [quasi] dynamique
et : Une énigme mathématique résolue avec MySQL
recommande l'utilisation de PDO (PHP5 Data Objects)
Maljuna Kris est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 17h26   #9
Invité de passage
 
Inscription : novembre 2006
Messages : 10
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 10
Points : 1
Points : 1
Tout d'abord merci à vous pour vos réponses.

Citation:
Envoyé par Maljuna Kris Voir le message
Saluton,
Il te faut mettre la table en jointure avec elle-même, faire un regroupement par produit, compter les lignes qui participent de la jointure et ne retenir que les regroupements dont l'effectif est égal à 2
Code sql :
1
2
3
4
5
6
7
8
SELECT c1.produit
FROM `catalogue_produit_specificite` AS c1
INNER JOIN `catalogue_produit_specificite` AS c2
ON c2.produit=c1.produit
AND c2.specificite IN (1,2)
AND c2.valeur IN (2,3)
GROUP BY c1.produit
HAVING COUNT(*) = 2
Attention toutefois, ce qui est sous-entendu dans cette requête c'est l'UNICITÉ des trios {produit, specificite, valeur} dans la table.
Si ce n'était pas le cas il faudrait remplacer
Code :
INNER JOIN `catalogue_produit_specificite` AS c2
par
Code :
INNER JOIN (SELECT DISTINCT produit, specificite, valeur FROM`catalogue_produit_specificite`) AS c2
Cette requête ne retourne aucun résultat. Je ne vois pas trop où tu veux en venir malheureusement avec le HAVING COUNT(*) donc je suis pas allé plus loin.

Par contre, je vois l'idée avec la jointure, que reprend d'ailleurs jeca :

Citation:
Envoyé par jeca Voir le message
Et comme ça :
Code :
1
2
3
4
5
SELECT a.produit 
FROM catalogue_produit_specificite a
JOIN catalogue_produit_specificite b ON a.produit = b.produit
WHERE (a.specificite=1 AND a.valeur=2) 
AND (b.specificite=2 AND b.valeur=3)
C'est cette solution que j'ai retenue car elle tient compte des couples {specificite, valeur}.

Cependant, j'ai plusieurs fois dans ma table plus de deux lignes pour un même produit (jusqu'à une trentaine).

Ça m'embête un peu d'utiliser PHP pour générer une requête avec un nombre de jointures aléatoires (30 jointures de la même table, c'est étrange, non ?).

N'y-a-t-il pas un moyen plus simple et plus "propre" ?

Au fait, pour l'unicité des valeurs, j'ai une clé unique qui m'empêche d'ajouter deux spécificités identiques pour un même produit :

2 1 2
2 1 3 --> impossible

Par contre, pas de problème pour :
2 1 2
2 2 2
2 3 2

Encore merci d'avance ;-)
affro-jojo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 18h23   #10
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
En reprenant l'idée du HAVING mais sans jointure, je pense que ça correspond à ce que tu recherches :
Code :
1
2
3
4
5
SELECT produit 
  FROM catalogue_produit_specificite 
 WHERE (specificite,valeur) IN ((1,2),(2,3))
 GROUP BY produit
HAVING count(*) = 2
En gros le IN n'est pas assez filtrant, tu récupères donc des couples (specificite,valeur) qui ne correspondent qu'à un des critères placés dans le IN.
Pour ne conserver que ceux qui les possèdent tous tu utilises HAVING count(*) = le_nombre_de_couples_placés_dans_le_IN.
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/06/2011, 18h36   #11
Invité de passage
 
Inscription : novembre 2006
Messages : 10
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 10
Points : 1
Points : 1
Citation:
Envoyé par skuatamad Voir le message
En reprenant l'idée du HAVING mais sans jointure, je pense que ça correspond à ce que tu recherches :
Code :
1
2
3
4
5
SELECT produit 
  FROM catalogue_produit_specificite 
 WHERE (specificite,valeur) IN ((1,2),(2,3))
 GROUP BY produit
HAVING count(*) = 2
En gros le IN n'est pas assez filtrant, tu récupères donc des couples (specificite,valeur) qui ne correspondent qu'à un des critères placés dans le IN.
Pour ne conserver que ceux qui les possèdent tous tu utilises HAVING count(*) = le_nombre_de_couples_placés_dans_le_IN.
Ok ! Je viens de comprendre ! Merci beaucoup, ça fonctionne à merveille ;-)

EDIT : Si ça peut aider quelqu'un, j'ai du ajouter DISTINCT pour HAVING COUNT(DISTINCT colonne) = nombre_de_couples
affro-jojo 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 02h07.


 
 
 
 
Partenaires

Hébergement Web