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

PHP & Base de données Discussion :

Requête double, rédaction.. [MySQL]


Sujet :

PHP & Base de données

  1. #1
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut Requête double, rédaction..
    Bonjour à tous et toutes,
    et merci de votre aide.

    Je rencontre un souci de rédaction d'une requête, qui me permet d'afficher un tri.
    Ma structure de tables :
    j'ai plusieurs tables : item, champ, et valeur_champ_item qui fait le lien entre l'item, le champ, et sa valeur.
    Par exemple : l'item "employe_1" a un champ "prenom" attribué, dont la valeur_champ_item est "gérard", et un champ nom attribué avec la valeur Durand.

    dans une requête de tri je souhaite afficher par exemple tous les employés dont la valeur prénom (id_champ_item 60) est vide. ce qui donne :
    ... AND (asso_valeur_champ_item.id_champ_item=60 AND asso_valeur_champ_item.valeur='') -> ça fonctionne.

    Là où j'ai un souci, c'est quand je demande un tri avec DEUX valeurs :
    ... AND (asso_valeur_champ_item.id_champ_item=60 AND asso_valeur_champ_item.valeur='') AND (asso_valeur_champ_item.id_champ_item=65 AND asso_valeur_champ_item.valeur='')

    Mon résultat est 0, alors que je sais que 4 items sont concernés.

    Je pense que le problème vient du fait que je demande deux fois des attributions de valeur_champ_item. J'ai mis des parenthèses pour bien délimiter le fait que je demande (id_champ_item=60 AND asso_valeur_champ_item.valeur='') ET AUSSI (id_champ_item=65 AND asso_valeur_champ_item.valeur='')

    Auriez-vous une idée ?

    Merci par avance,

    PF

  2. #2
    Membre Expert Avatar de darkstar123456
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2008
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 895
    Par défaut
    Bonjour,

    C'est compliqué de pouvoir apporter de l'aide avec des bribes de code (de requête dans ce cas-ci ^^)

    Mais ce que je peux dire, c'est que s'il faut comparer plusieurs valeurs d'une même colonne (asso_valeur_champ_item), il faut soit faire plusieurs requêtes; soit loader plusieurs fois la même table avec des JOIN; il faut ensuite comparer la première valeur par rapport à la "première" table; et la seconde valeur par rapport à la "seconde" table

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT * FROM ma_table AS t1
    LEFT JOINT ma_table_de_cles AS c1 ON c1.ID = t1.ID
    LEFT JOINT ma_table_de_cles AS c2 ON c2.ID = t1.ID
    WHERE c1.ma_cle = 'prenom' AND c1.valeur = '' AND c2.ma_cle = 'nom' AND c2.valeur = ''

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    188
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 188
    Par défaut
    Bonjour,

    Je dirai qu'il faut faire autant de liaisons entre les tables que tu as de critères de sélections.

    par exemple
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT * FROM  maTable 
    INNER JOIN asso_valeur_champ_item as asso_valeur_champ_item1 ON maTable.id=asso_valeur_champ_item1.id
    INNER JOIN asso_valeur_champ_item as asso_valeur_champ_item2 ON maTable.id=asso_valeur_champ_item2.id 
    WHERE (id_champ_item=60 AND asso_valeur_champ_item1.valeur='')  AND (id_champ_item=65 AND asso_valeur_champ_item2.valeur='')

    je ne connais pas le nom des champs etc.. de ta base mais c'est le principe.

  4. #4
    Inactif  
    Homme Profil pro
    Webmaster
    Inscrit en
    Juin 2021
    Messages
    645
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juin 2021
    Messages : 645
    Par défaut
    Bonjour,
    C'est un problème de logique.

    "ET AUSSI" : dans la requête, ce sera OR
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    ... AND ( (condition 1) OR (condition 2) ) AND ...
    Les parenthèses ont aussi leur importance.

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ... 
    AND (
       (asso_valeur_champ_item.id_champ_item=60 AND asso_valeur_champ_item.valeur='')
       OR
       (asso_valeur_champ_item.id_champ_item=65 AND asso_valeur_champ_item.valeur='')
    )
    ...
    Ne pas hésiter à indenter le code, pour la lisibilité et le débogage.

  5. #5
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut
    Bonjour et merci beaucoup de votre aide, c'est chouette de ne pas se sentir toute seule !

    @wehtam et @darkstar123456 :
    mon problème ne réside pas au niveau de la jointure.
    Concrètement la forme de la requête qui me pose problème se situe dans une seule et unique table.

    Mes tables sont :
    • Employes : les employés
    • champ_item : les critères possibles pour les employés
    • asso_valeur_champ_item : table qui contient l'association des valeurs des critères avec les employés. Par exemple : critère "permis caces" : 1 pour oui, critère "permis grue", 1 pour oui.


    donc j'ai dans la table asso_valeur_champ_item des lignes du type :

    • id_employe : 1 par exemple.
    • id_champ_item : 27 (par exemple, car c'est l'id du critère permis caces)
    • valeur : 1 ou 0


    • id_employe : 2 par exemple.
    • id_champ_item : 27
    • valeur : 1 ou 0


    • id_employe : 1 par exemple.
    • id_champ_item : 7 (par exemple, car c'est l'id du critère permis grue)
    • valeur : 1 ou 0


    etc.

    En Français ma requête problématique donnerait :
    Sélectionne dans la table " asso_valeur_champ_item " tous les employés dont l'"id_champ_item" 27 a pour valeur '1' ET dont l'"id_champ_item" 7 a pour valeur '1'
    pour sélectionner ceux qui ont le permis caces ET AUSSI le permis grue.


    ---

    @jreaux62 : Je ne connaissais pas la syntaxe "AND OR", est-ce une erreur dans ta réponse ? cela génère une erreur
    Fatal error: Call to a member function fetch_assoc() on boolean in ...
    ---

    j'ai testé en dur ma requête:
    si je mets juste :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    AND (asso_valeur_champ_item.id_champ_item=27 AND asso_valeur_champ_item.valeur = '1') --> pour avoir ceux qui ont le permis caces
    j'ai 29 résultats.

    si je mets juste :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    AND (asso_valeur_champ_item.id_champ_item=7 AND asso_valeur_champ_item.valeur = '1') --> pour avoir ceux qui ont le permis grue
    j'ai 29 résultats (ce sont les mêmes qui ont le permis grue et le caces).

    mais si je mets :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    AND (asso_valeur_champ_item.id_champ_item=27 AND asso_valeur_champ_item.valeur = '1') AND (asso_valeur_champ_item.id_champ_item=7 AND asso_valeur_champ_item.valeur = '1')
    ou
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    AND ((asso_valeur_champ_item.id_champ_item=27 AND asso_valeur_champ_item.valeur = '1') AND (asso_valeur_champ_item.id_champ_item=7 AND asso_valeur_champ_item.valeur = '1'))
    je devrais avoir 29 résultats car ce sont les mêmes items qui ont ces valeurs pour ces critères, mais j'ai 0 résultats.

    Peut-être que je devrais essayer de faire des requêtes imbriquées du style
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select * from asso_valeur_champ_item WHERE  (id_champ_item=27 AND valeur = '1')
    ... WHILE(mes resultats des id_employe qui ont le caces){
        select * from asso_valeur_champ_item WHERE  (id_champ_item=7 AND valeur = '1') AND id_asso_valeur_champ_item=$row[id_employe]
        ... WHILE(){
        ...etc.
    Mais j'ai une trentaine de tris qui peuvent être possibles, voir plus car la création de critères n'est pas limitée et je trouve ça moyennement propre comme requête, et potentiellement lent...

    Qu'en pensez-vous ?

  6. #6
    Membre Expert Avatar de darkstar123456
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2008
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 895
    Par défaut
    Bonjour,

    Vous dites que tout ce situe dans une seule et unique table, et puis vous listez "Mes tables sont :"

    En tout cas, les 2 solutions (celle de @jreaux62, ainsi que celle de @wehtam et moi -qui avons donné la même-), fonctionnent et dépendent à la fois de la structure de la DB et de ce qu'on cherche.

    mais si je met :
    AND (asso_valeur_champ_item.id_champ_item=27 AND asso_valeur_champ_item.valeur = '1') AND (asso_valeur_champ_item.id_champ_item=7 AND asso_valeur_champ_item.valeur = '1')
    ou
    AND ((asso_valeur_champ_item.id_champ_item=27 AND asso_valeur_champ_item.valeur = '1') AND (asso_valeur_champ_item.id_champ_item=7 AND asso_valeur_champ_item.valeur = '1'))
    je devrais avoir 29 résultats car ce sont les mêmes items qui ont ces valeurs pour ces critères, mais j'ai 0 résultats.
    C'est 2 requêtes sont exactement identiques : en logique, pour qu'une condition AND soit vraie, elles doivent toutes êtres vraies. Du coup, les parenthèses n'ont aucune incidence.

    Si vous ne trouvez pas de résultat c'est parce que vous chercher des employés qui ont la valeur nom ET prénom à X (1 ici)
    Est-ce vraiment ça que vous cherchez ? Parce que ce n'est pas parce que 3 employés ont le prénom "Alfred" et que 2 employés ont le nom "Tartampion", qu'il y a 5 "Alfred Tartampion" dans l'entreprise. Il est même probable qu'il y en ait aucun.
    Il faut alors inclure un OR comme l'a fait @jreaux62 (le AND OR est une coquille)

    Ca donnerait ceci :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    AND ((asso_valeur_champ_item.id_champ_item=27 AND asso_valeur_champ_item.valeur = '1') OR (asso_valeur_champ_item.id_champ_item=7 AND asso_valeur_champ_item.valeur = '1'))
    Et ici, les parenthèses ont de l'importance !!

    PS : Ma première solution inclus des jointures car, je me trompe peut-être, mais il me semble qu'il est moins gourmand de faire des jointures et de n'avoir que des AND dans sa requête plutôt que d'avoir des OR qui sont normalement plus gourmands

  7. #7
    Inactif  
    Homme Profil pro
    Webmaster
    Inscrit en
    Juin 2021
    Messages
    645
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juin 2021
    Messages : 645
    Par défaut
    oups...

    @jreaux62 : Je ne connaissais pas la syntaxe "AND OR", est-ce une erreur dans ta réponse ?
    oui, une erreur de copier-coller (pas relu/vu la fin de la ligne car j'étais sur ma mini-tablette ).
    C'est juste OR.

    Par contre, je n'avais pas bien saisi la problématique de base...
    j'ai plusieurs tables : item, champ, et valeur_champ_item qui fait le lien entre l'item, le champ, et sa valeur.
    et asso_valeur_champ_item ???

    Il faut faire des JOINTURES (INNER JOIN,...) entre les tables, et leur mettre des ALIAS, pour éviter les confusions de champs (si même nom dans plusieurs tables).


    N.B. AU LIEU DE BAVARDER, tu aurais mieux fait de montrer :
    • la structure des TABLES (sérieux... elle s'appellent vraiment "item","champ","..." ?)
    • La REQUETE (complète)

    On aurait gagné du temps.

  8. #8
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut
    @jreaux62

    à mon tour d'avoir fait une erreur, je répondais avec mon téléphone
    valeur_champ_item - > asso_valeur_champ_item

    Bon... pardon de persister, mais ma requête ne se fait que sur une seule table. J'en appelle plusieurs simplement pour afficher d'autres valeurs de critères qui sont dans d'autres tables, mais pas pour les trier.
    Comme je vous l'ai dit tout ceci est dynamique, et la table asso_valeur_champ_item contient les champs "table_concernee" et "id_item" qui peuvent prendre des valeurs diverses comme appeler la table "employe", "materiel", "chantier" etc.
    Ainsi, en joignant la table concernée dans ma requête, je peux afficher le nom de mon item, qui sera le nom d'un employé, d'un véhicule, ou d'un chantier etc. sans faire de nouvelle requête. D'où l’appellation large "item" qui me convient bien.

    Trève de bavardage, j'ai simplifié ma requête pour ne me concentrer que sur asso_valeur_champ_item et faciliter votre compréhension.
    Sa structure :
    id_asso_valeur_champ_item
    id_item
    table_concernee
    id_champ_item
    valeur

    Je veux afficher :
    Tous les id_item dont
    la table_concernee est "employe"
    ET
    (
    (l'id_champ_item est 7 ET la valeur est 1)
    ET
    (l'id_champ_item est 27 ET la valeur est 1)
    )

    si je met "OR" je vais avoir l'un OU l'autre, mais moi je veux l'un ET l'autre, c'est à dire dans mon exemple les employés qui ont à la fois le permis caces et le permis grue.

    Voici une requête qui fonctionne, que j'envisageais à la fin de mon dernier post.
    Est-il possible de la simplifier ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
            $req_tri_table1 = $client->query("SELECT * FROM asso_valeur_champ_item WHERE 
    	table_concernee='employe'
    	AND (id_champ_item=27 AND valeur = '1')
    	");
    	while ($row_req_tri_table1 = $req_tri_table1->fetch_assoc()) {
     
                    // là je boucle tous les employés qui ont le caces, et pour chacun j'envoie une requête
    		$req_tri_table2 = $client->query("SELECT * FROM asso_valeur_champ_item WHERE 
    		id_item=$row_req_tri_table1[id_item]
                    AND table_concernee='employe'
    		AND (id_champ_item=7 AND valeur = '1') // parmis eux, je cherche ceux qui ont le permis grue
    		");
     
    		while ($row_req_tri_table2 = $req_tri_table2->fetch_assoc()) {
    			echo $row_req_tri_table2['id_item']; // et voilà la liste de ceux qui ont à la fois le caces et le permis grue
    		}
    	}
    Du coup, dans cet exemple je crée une requête qui en lance 32 autres.
    Et si dans ma recherche je veux ceux qui ont le caces, le permis grue, chaussent du 44, sont nés après 1918, et parlent le néerlandais ça va faire un paquet de requêtes

    Merci de votre aide,

    E.

  9. #9
    Inactif  
    Homme Profil pro
    Webmaster
    Inscrit en
    Juin 2021
    Messages
    645
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juin 2021
    Messages : 645
    Par défaut
    bonjour,

    tu n'as pas compris l'utilisation d'une table de liaison.

    Tu ne peux pas faire une requête sur cette unique table.
    Il faut faire des JOINTURE sur les autres tables concernées.

    Il me semble que l'approche de wehtam est la bonne.

    A tester :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    "SELECT * 
    FROM item ITM
    INNER JOIN asso_valeur_champ_item AS1
    	ON ITM.id_item = AS1.id_item
    INNER JOIN asso_valeur_champ_item AS2
    	ON ITM.id_item = AS2.id_item
    WHERE 
    	ITM.id_item = $row_req_tri_table1[id_item]
    	AND ( AS1.table_concernee = 'employe' AND AS1.id_champ_item = 7 AND AS1.valeur = 1 )
    	AND ( AS2.table_concernee = 'employe'  AND AS2.id_champ_item = 27 AND AS2.valeur = 1 )
    ;"
    ITM, AS1 et AS2 sont des ALIAS des tables (pour une meilleure lisibilité du code)

    IMPORTANT : il faudrait ici utiliser une requête préparée, et mettre $row_req_tri_table1[id_item] en paramètre.

  10. #10
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut
    bonjour jreaux62,

    en effet c'est la première fois que j'ai à utiliser une table de liaison de cette sorte, et je comprend un peu mieux mon erreur avec ton explication... Et je ne maîtrise pas non plus la notion de préparation des requêtes.

    Il y a un point obscure qui me bloque dans ton exemple, je n'arrive pas à le transposer à mon cas.
    Je n'ai pas de table "item", si bien que je ne sais pas si tu désignes par "item" la table qui pourrait être chez moi la table "employe" ou "materiel" puisque c'est ce qu eje désigne par "item", ou si tu parles de la table "champ_item".
    étant donné que je cherche la liste des employés, je pense que c'est de la table "employe" que tu parles.
    Mais alors qu'est-ce que je dois mettre dans la requête préparée ?
    dans mon exemple que tu reprends, le résultat $row_req_tri_table que tu me dis de préparer donnait les id_employe dont la valeur de l'id_champ_item 7 était 1, ce qui n'aurait pas de sens ici.

    à wehtam : en partant de ton exemple, j'ai créé cette requête, qui ne renvoie rien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $req_tri_tablex = $client->query("SELECT * FROM  employe 
    INNER JOIN asso_valeur_champ_item as asso_valeur_champ_item1 ON employe.id_employe=asso_valeur_champ_item1.id_item
    INNER JOIN asso_valeur_champ_item as asso_valeur_champ_item2 ON employe.id_employe=asso_valeur_champ_item2.id_item
    WHERE (asso_valeur_champ_item1.id_champ_item=27 AND asso_valeur_champ_item1.valeur='1' AND asso_valeur_champ_item1.table_concernee='employe')  AND (asso_valeur_champ_item2.id_champ_item=7 AND asso_valeur_champ_item2.valeur='2' AND asso_valeur_champ_item2.table_concernee='employe')");
    	while ($row_req_tri_tablex = $req_tri_tablex->fetch_assoc()) {
    			echo $row_req_tri_tablex['id_employe']."<br />";
    		}
    Je vous met une image de la structure de mes tables

    Nom : SCHEMA.jpg
Affichages : 75
Taille : 100,0 Ko

    merci,

  11. #11
    Membre averti
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2014
    Messages : 24
    Par défaut
    @wehtam

    C'est OK, la requête fonctionne, c'est que personne ne remplissait les critères demandés !

    @jreaux62 : je vais plancher sur les requêtes préparées pour améliorer tout ça,

    Merci de votre aide en tout cas

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

Discussions similaires

  1. [PHP 5.3] Soucis avec le résultat d'une requête (double boucles while)
    Par beegees dans le forum Langage
    Réponses: 7
    Dernier message: 31/05/2010, 22h26
  2. Résultat de requête doublé
    Par ZeDave dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 07/02/2008, 16h08
  3. Problème : Requête double les enregistrements !
    Par Aost dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 22/06/2006, 17h44
  4. requète double en 1 fois
    Par Yoshio dans le forum Débuter
    Réponses: 10
    Dernier message: 15/01/2006, 23h37
  5. [Requête] Requête double, "OU" entre requêtes.
    Par muphin dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 21/06/2005, 15h04

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