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 :

jointure de trois tables (pb d'ambiguité)


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juillet 2009
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 81
    Par défaut jointure de trois tables (pb d'ambiguité)
    Bonjour

    Je voudrais joindre trois tables :
    Attribuer (id_perso , id_aff , nb_heures)
    Personnel (id_perso ,nom_perso)
    Affaire (id_aff , d_date)

    Voici le code (aidé par CinePhil) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $requete = "SELECT p.id_perso, p.nom_perso, p.prenom,
      a.id_aff,
      SUM(a.nb_heures) AS nb_heures_total
    FROM personnel p
     
    INNER JOIN attribuer a ON a.id_perso = p.id_perso
     
    where `id_aff` LIKE CONVERT( _utf8 '%$id_affaire%'USING latin1 )
    AND `nom_perso` LIKE CONVERT( _utf8 '%$nom_agent%'USING latin1 )
    GROUP BY p.id_perso, p.nom_perso, p.prenom, a.id_aff
    ORDER BY a.id_aff , p.nom_perso, p.prenom  desc
                 ";
    Je voudrais rajouter une jointure avec la table affaire (dans laquelle il y a un champ d_date) qui croise la table attribuer via le champ id_aff, afin de filtrer les résultats par date (via un AND d_date>='$deb'and d_date<='$fi' )
    Si je rajoute la ligne INNER JOIN affaire af ON af.id_aff = a.id_aff

    il dit : Column 'id_aff' in where clause is ambiguous

    Et si pour lever l'ambiguité je change la ligne par

    where `a.id_aff` LIKE CONVERT( _utf8 '%$id_affaire%'USING latin1 )

    ça me répond :
    Unknown column 'a.id_aff' in 'where clause'

    Quelle est mon erreur ?

    Cordialement,
    Philippe Rivière

  2. #2
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 : 16 818
    Billets dans le blog
    14
    Par défaut
    Quand tu utilises les alias - et c'est important de les utiliser dès qu'une requête utilise plus d'une table - il faut les utiliser partout !

    Et supprime donc ces saloperies d'apostrophes inversées inutiles dès lors que tes tables et colonnes sont correctement nommées !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT p.id_perso, p.nom_perso, p.prenom,
      a.id_aff,
      SUM(a.nb_heures) AS nb_heures_total
    FROM personnel p
    INNER JOIN attribuer a ON a.id_perso = p.id_perso
    WHERE a.id_aff LIKE CONVERT( _utf8 '%$id_affaire%' USING latin1 )
    	AND p.nom_perso LIKE CONVERT( _utf8 '%$nom_agent%' USING latin1 )
    GROUP BY p.id_perso, p.nom_perso, p.prenom, a.id_aff
    ORDER BY a.id_aff , p.nom_perso, p.prenom  desc
    Pourquoi es-tu obligé de t'emmerder avec les CONVERT ? id_aff devrait être de type entier, tout comme id_perso et tout identifiant de ligne d'une table issue d'une entité du MCD ou comme toute clé étrangère.

    En plus, ta requête va être contre performante du fait du LIKE '%chaine%' et le CONVERT ne va pas arranger les choses ! J'espère que le volume de données n'est pas trop important sinon ça va ramer !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « 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 la suite Linux Mageïa !

  3. #3
    Membre confirmé
    Inscrit en
    Juillet 2009
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 81
    Par défaut
    Ok merci si je comprends bien c'est qu'il fallait utiliser les alias partout.
    Maintenant cela fonctionne.

    Ensuite pour les convert, curieusement si je ne les utilise pas, ça ne marche pas.

    Enfin pour le LIKE '%chaine%' c'est pour pouvoir avoir qu'une seul requête même si les champs sont vides.

    Par exemple, j'ai deux champs de recherche et avec LIKE '%chaine%' si les deux champs sont vide et que je lance une recherche ça recherche tout, sinon il faut que je fasse trois condition en fonction que les champs sont vide ou pas.

    Mais si tu connais une façon d'avoir une seule requête sql sans le LIKE '%chaine%', ça m'intéresse.

    Citation Envoyé par CinePhil Voir le message
    Quand tu utilises les alias - et c'est important de les utiliser dès qu'une requête utilise plus d'une table - il faut les utiliser partout !

    Et supprime donc ces saloperies d'apostrophes inversées inutiles dès lors que tes tables et colonnes sont correctement nommées !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT p.id_perso, p.nom_perso, p.prenom,
      a.id_aff,
      SUM(a.nb_heures) AS nb_heures_total
    FROM personnel p
    INNER JOIN attribuer a ON a.id_perso = p.id_perso
    WHERE a.id_aff LIKE CONVERT( _utf8 '%$id_affaire%' USING latin1 )
    	AND p.nom_perso LIKE CONVERT( _utf8 '%$nom_agent%' USING latin1 )
    GROUP BY p.id_perso, p.nom_perso, p.prenom, a.id_aff
    ORDER BY a.id_aff , p.nom_perso, p.prenom  desc
    Pourquoi es-tu obligé de t'emmerder avec les CONVERT ? id_aff devrait être de type entier, tout comme id_perso et tout identifiant de ligne d'une table issue d'une entité du MCD ou comme toute clé étrangère.

    En plus, ta requête va être contre performante du fait du LIKE '%chaine%' et le CONVERT ne va pas arranger les choses ! J'espère que le volume de données n'est pas trop important sinon ça va ramer !

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Qu'est ce que ça donne comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    WHERE a.id_aff = coalesce($id_affaire, a.id_aff)
      AND p.nom_perso = coalesce($nom_agent, p.nom_perso)
    Par contre j'ai pas compris les convert qui sont peut être vraiment utile.

    Mais ce n'est pas une bonne solution, il est préférable de construire dynamiquement la requête dans le code php en fonction des paramètres NULL ou non.
    L'objectif est de soumettre au SGBD la requête qui correspond vraiment au besoin, comme ça le SGBD peut choisir d'utiliser un index pour certaines combinaisons de paramètre et un scan complet en l'absence de paramètre, par exemple.

  5. #5
    Membre confirmé
    Inscrit en
    Juillet 2009
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 81
    Par défaut
    Quand je met ton code ça me renvoi ceci :

    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' a.id_aff) AND p.nom_perso = coalesce(, p.nom_perso) AND d_date>='2011-01-' at line 7

    Pour les convert, je pense que je dois les utiliser, du fait que la BDD doit être mal construite, genre des mélange d'UTF8 avec du latin...

    "en fonction des paramètres NULL ou non" comment ça ?

    Citation Envoyé par skuatamad Voir le message
    Qu'est ce que ça donne comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    WHERE a.id_aff = coalesce($id_affaire, a.id_aff)
      AND p.nom_perso = coalesce($nom_agent, p.nom_perso)
    Par contre j'ai pas compris les convert qui sont peut être vraiment utile.

    Mais ce n'est pas une bonne solution, il est préférable de construire dynamiquement la requête dans le code php en fonction des paramètres NULL ou non.
    L'objectif est de soumettre au SGBD la requête qui correspond vraiment au besoin, comme ça le SGBD peut choisir d'utiliser un index pour certaines combinaisons de paramètre et un scan complet en l'absence de paramètre, par exemple.

  6. #6
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 : 16 818
    Billets dans le blog
    14
    Par défaut
    Pour l'erreur que tu rencontres, je pense qu'il faut entourer la variable PHP d'apostrophes. Mais je suis d'accord avec skuatamad : construit ta requête dynamiquement dans le code applicatif en fonction de ce qui est saisi par l'utilisateur. Et si tu peux éviter le CONVERT en remettant tout en UTF8, c'est mieux.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « 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 la suite Linux Mageïa !

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

Discussions similaires

  1. Jointure sur trois tables
    Par user126 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/02/2008, 17h07
  2. Criteria jointure de trois tables
    Par MrX dans le forum Hibernate
    Réponses: 2
    Dernier message: 12/12/2007, 11h56
  3. Jointure avec trois tables, je n'y arrive pas.
    Par sunshine33 dans le forum Langage SQL
    Réponses: 8
    Dernier message: 16/02/2007, 09h52
  4. [SQL Server 8] Discussion : Full Jointure sur trois tables
    Par Baquardie dans le forum Langage SQL
    Réponses: 5
    Dernier message: 22/12/2006, 14h01
  5. jointure sur TROIS tables
    Par caribou_belle dans le forum Langage SQL
    Réponses: 8
    Dernier message: 01/03/2004, 11h20

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