IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Recherche avec critères sur plusieurs lignes


Sujet :

Requêtes MySQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 8
    Points
    8
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    INNER JOIN `catalogue_produit_specificite` AS c2
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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)

  3. #3
    Membre expérimenté

    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 060
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 060
    Points : 1 357
    Points
    1 357
    Par défaut
    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.

  4. #4
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    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)

  5. #5
    Membre expérimenté

    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 060
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 060
    Points : 1 357
    Points
    1 357
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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)

  6. #6
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    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)

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Août 2002
    Messages
    1 060
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 1 060
    Points : 1 357
    Points
    1 357
    Par défaut
    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.

    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 :
    2
    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
    2
    2
    Donc le tout est de savoir si plusieurs lignes identiques peuvent exister.

  8. #8
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

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

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    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)

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    INNER JOIN `catalogue_produit_specificite` AS c2
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 ;-)

  10. #10
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    En reprenant l'idée du HAVING mais sans jointure, je pense que ça correspond à ce que tu recherches :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 8
    Points
    8
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2003] Recherche de plusieurs critères sur plusieurs lignes puis addition du nombre
    Par iIncoming dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 20/03/2014, 05h45
  2. Menu avec select sur plusieurs lignes
    Par jfox dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 23/07/2012, 15h11
  3. [AC-2007] plusieurs counts avec critères sur plusieurs champs
    Par edogawa59 dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 11/10/2010, 15h32
  4. Réponses: 2
    Dernier message: 10/09/2010, 15h43
  5. Réponses: 6
    Dernier message: 18/03/2007, 16h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo