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 :

[LEFT JOIN] Condition de jointure bizzare [Fait]


Sujet :

Requêtes MySQL

  1. #1
    Membre éprouvé
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Points : 1 122
    Points
    1 122
    Par défaut [LEFT JOIN] Condition de jointure bizzare
    Bonjour,

    Je vous explique :
    j'ai une table `epreuves` qui a entre autre un champ epreuve_id, et une table `validation` qui a entre autre un champ epreuve_id et un champ user_id.

    Étant donné que plusieurs users peuvent valider la même épreuve, j'ai une relation de type 1:n.

    Je voudrais simplement récupérer les infos de la table `epreuves` connaissant l'id de l'épreuve. Et en même temps savoir si l'user a déjà validé l'épreuve.

    En fait ma requête ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT ep.reponse, ep.points, val.date_valid
    	FROM `challenges_epreuves` AS ep
    	LEFT JOIN `challenges_validation` AS val ON (ep.id_epreuve=val.id_epreuve AND val.user_id=$user_id)
    	WHERE ep.id_epreuve=$idep
    Voilà, je n'ai rien trouvé de mieux que de mettre AND val.user_id=$user_id dans la condition de jointure. Je trouve que ça fait un peu sale de mettre dans le ON une condition qui ne fait pas intervenir les 2 tables.

    Y'a-t-il une autre façon de faire que je n'aurais pas vu ?
    Ou sinon est-ce généralisable à d'autres cas ?


    Merci d'avance
    Les vaches ne peuvent PAS voler, quoi qu'elles aient pu vous raconter.

  2. #2
    Membre expert
    Avatar de trotters213
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 571
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Gard (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 571
    Points : 3 145
    Points
    3 145
    Par défaut

    tu as essayé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT ep.reponse, ep.points, val.date_valid
    FROM challenges_epreuves AS ep LEFT OUTER JOIN challenges_validation AS val ON ep.id_epreuve=val.id_epreuve
    WHERE ep.id_epreuve=$idep 
      AND val.user_id=$user_id
    :

  3. #3
    Membre éprouvé
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Points : 1 122
    Points
    1 122
    Par défaut
    Oui je viens de tester, et le résultat est bien celui que je pensait : si l'épreuve n'a pas été validé ça ne me retourne aucun enregistrement.

    Avec ta requête mysql va commencer par réaliser la jointure externe, c'est à dire qu'à tous les enregistrement de challenges_epreuves on associe les enregistrements de la table challenges_validation (ou null si il n'y en a pas), puis la clause WHERE restreint la sélection aux lignes où id_epreuve et user_id ont la valeur demandé ; or si l'user n'a pas validé l'épreuve en question je n'aurais plus aucun enregistrement sélectionné.

    Alors qu'en posant la restriction du user_id dans le ON, à chaque enregistrement de challenges_epreuves on associe un enregistrement de challenges_validation si et seulement si c'est l'user en question qui l'a validé (sinon null). Puis la clause WHERE restreint la sélction à l'épreuve souhaité.
    Les vaches ne peuvent PAS voler, quoi qu'elles aient pu vous raconter.

  4. #4
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut Re: [LEFT JOIN] Condition de jointure bizzare
    Citation Envoyé par Celelibi
    En fait ma requête ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT ep.reponse, ep.points, val.date_valid
    	FROM `challenges_epreuves` AS ep
    	LEFT JOIN `challenges_validation` AS val ON (ep.id_epreuve=val.id_epreuve AND val.user_id=$user_id)
    	WHERE ep.id_epreuve=$idep
    Voilà, je n'ai rien trouvé de mieux que de mettre AND val.user_id=$user_id dans la condition de jointure. Je trouve que ça fait un peu sale de mettre dans le ON une condition qui ne fait pas intervenir les 2 tables.
    En effet ça ne me parait pas très orthodoxe

    Tu as essayé ceci ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT ep.reponse, ep.points, val.date_valid
    FROM challenges_epreuves AS ep LEFT OUTER JOIN challenges_validation AS val ON ep.id_epreuve=val.id_epreuve
    WHERE ep.id_epreuve=$idep
      AND (val.user_id=$user_id OR val.user_id IS NULL)
    Pensez au bouton

  5. #5
    Membre expérimenté
    Avatar de Adjanakis
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    739
    Détails du profil
    Informations personnelles :
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Avril 2004
    Messages : 739
    Points : 1 351
    Points
    1 351
    Par défaut
    Bonjour,

    Dans la première requête, il est possible de remplacer la table challenges_validation par une vue ou une requête du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select * from challenges_validation where val.user_id=$user_id
    Je viens de tester ce type de solution sur mon serveur de test... ça semble fonctionner.
    Pensez au tag

  6. #6
    Membre éprouvé
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Points : 1 122
    Points
    1 122
    Par défaut
    à Maximilian :

    Et non ceci ne me renvoi encore et toujours aucun enregistrement.

    Si j'ai bien capté le fonctionnement des jointures externes, à chaque enregistrement de la première table on associe un enregistrement de la 2eme table selon la condition de jointure précisé dans le ON. Et si aucun enregistrement de la 2eme table ne corresspond à la condition, on met NULL.

    Et dans mon cas le champ id_epreuve aura toujours au moins une corresspondance dans la table challenges_validation car d'autres users auront validés l'épreuve en question. Donc je n'aurais aucun enregistrement de challenges_epreuves qui aurai une corresspondance NULL si je me contente de faire la jointure sur le champ id_epreuve.


    à Adjanakis :
    Oui j'ai déjà pensé à faire une sous requête, ça doit marcher aussi bien que ma requête actuelle. De toutes façon ça revient au même car moi je ne fais la jointure que si l'user_id est bon, et avec une sous-requête tu garde seulement le bon user_id avant de faire la jointue : ce qui revient même.
    Je préfère quand même éviter les sous-requêtes, pour des raisons de ressources système et de plus le site est actuellement sur free qui en est encore à mysql 4.0.22 : version qui ne supporte pas les sous-requêtes.

    Je pense qu'il doit quand même exister un moyen plus orthodoxe et sans sous-requêtes de faire la même chose.
    Les vaches ne peuvent PAS voler, quoi qu'elles aient pu vous raconter.

  7. #7
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Bon tout compte fait ta première requête (avec le "AND val.user_id=$user_id" dans le ON) n'est pas si "sale" que ça

    En effet d'après la doc,

    You should generally not have any conditions in the ON part that are used to restrict which rows you want in the result set, but rather specify these conditions in the WHERE clause. There are exceptions to this rule.
    Qui plus est si l'on en croit le premier user comment sur cette page, c'est dans le ON qu'on établit les critères sur la table de droite (challenges_validation dans notre cas) alors que le WHERE sert pour la table de gauche (challenges_epreuves) :
    The join_condition is used for winnowing the
    rows of the "right half" that you want to use for
    the cross, whereas the WHERE clause is used for
    winnowing the composite.
    Ce qui est confirmé (avec plus de précision) dans le cours de SQLPro :

    La clause WHERE est un filtre d'élimination. Il suppose que les différentes tables sont déjà jointes en une seule et parcoure l'ensemble des résultats à la recherche des lignes correspondant aux critères donnés.

    En revanche la clause JOIN se comporte différemment. Elle agit AVANT que la jointure soit effective.

    Dans le cadre d'une jointure INTERNE le comportement est similaire à celui d'une clause WHERE.

    Dans le cas d'une jointure externe il faut décomposer la logique en plusieurs étapes :
    1) évaluation des éléments du prédicat
    2) application de la jointure : lignes jointe en 1)
    + lignes sans correspondance
    Pensez au bouton

  8. #8
    Membre éprouvé
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Points : 1 122
    Points
    1 122
    Par défaut
    Bon et bien merci bien. Maintenant je ne me dirais plus "c'est caca cette syntaxe" quand je suis obligé de l'employer.

    Donc si j'ai bien tout compris, on doit utiliser ce genre de syntaxe quand on veut poser une restriction sur une table avant de faire la jointure.


    Et bien merci bien tout le monde, ce sujet est résolu.
    Les vaches ne peuvent PAS voler, quoi qu'elles aient pu vous raconter.

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

Discussions similaires

  1. Réponses: 12
    Dernier message: 12/03/2008, 16h56
  2. Requête de jointure LEFT, quelles conditions?
    Par Woufeigh dans le forum Langage SQL
    Réponses: 2
    Dernier message: 03/12/2007, 11h56
  3. Jointures INNER JOIN LEFT JOIN
    Par tizla dans le forum Requêtes et SQL.
    Réponses: 10
    Dernier message: 31/05/2007, 12h12
  4. Réponses: 6
    Dernier message: 23/01/2007, 10h17
  5. Oraclei : LEFT JOIN et conditions
    Par alexadvance dans le forum Oracle
    Réponses: 9
    Dernier message: 02/11/2005, 15h22

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