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

Langage SQL Discussion :

Inner join avec condition


Sujet :

Langage SQL

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 155
    Points : 74
    Points
    74
    Par défaut Inner join avec condition
    Bonjour,

    Voici une question théorique sql, quelque soit le sgbdr il me semble.
    Je voulais savoir quelle est la différence entre ces 2 requêtes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          Select a.*, b.*
          from t1 a inner join t2 b 
                   on (a.c1 = b.c1)
          where a.c2 = 'xx';
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          Select a.*, b.*
          from t1 a inner join t2 b 
                   on (a.c1 = b.c1 and a.c2 = 'xx');

    Il me semble que la 2nde requête est plus performante parce que la restriction sur a.c2 se fait dès la jointure.

    Mais il me semble aussi que les résultats de ces requêtes ne sont pas toujours les mêmes ?

    Qu'en pensez-vous ?

    Merci d'avance de vos éclaircissements.

    Cordialement.

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Dans ce cas de figure, les deux requêtes sont strictement identiques.

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 774
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 774
    Points : 52 746
    Points
    52 746
    Billets dans le blog
    5
    Par défaut
    Pour la jointure interne les résultats sont identiques, ce qui n'est pas le cas pour la jointure externe. En effet les critères (ON) d'une jointure (JOIN) sont évaluées avant l'opération de jointure et la restriction (WHERE) après.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 155
    Points : 74
    Points
    74
    Par défaut
    Merci, vos réponses sont claires, alors pour une jointure externe (on suppose que a.c1 clé étrangère optionnelle (et que peuvent y subsister d'anciennes clés de b n'existant plus (si c'est possible)) et b.c1 clé primaire):

    Req1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          SELECT a.*, b.*
          FROM t1 a left outer JOIN t2 b 
                   ON (a.c1 = b.c1)
          WHERE b.c1 is null;
    Req2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          SELECT a.*, b.*
          FROM t1 a left outer JOIN t2 b 
                   ON (a.c1 = b.c1 and b.c1 is null);
    Req3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          SELECT a.*, b.*
          FROM t1 a left outer JOIN t2 b 
                   ON (a.c1 = b.c1 and a.c1 is null);
    Req4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          SELECT a.*, b.*
          FROM t1 a left outer JOIN t2 b 
                   ON (a.c1 = b.c1)
         WHERE a.c1 is null;
    On peut supposer pour :

    Req1 : retourne des lignes si a.c1 est une ancienne clé primaire de b n'existant plus (clés primaires nulles de b non autorisées).

    Req2 : idem que Req1 ?

    Req3 : ne retourne pas lignes ?

    Req4 : retourne les lignes de t1 ayant a.c1 null, la jointure est inutile ?

    Que pensez-vous de mes suppositions ? Y a surement des erreurs !

    Cordialement.

  5. #5
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 032
    Points
    34 032
    Billets dans le blog
    14
    Par défaut
    Voir mon blog au sujet de la jointure externe et de la condition de restriction.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          SELECT a.*, b.*
          FROM t1 a LEFT OUTER JOIN t2 b 
                   ON (a.c1 = b.c1)
          WHERE b.c1 IS NULL;
    Req1 : retourne des lignes si a.c1 est une ancienne clé primaire de b n'existant plus (clés primaires nulles de b non autorisées).
    Ta requête 1 va retourner toutes les lignes de t1 (a) qui n'ont pas de correspondance dans t2 (b).

    Cela n'a pas forcément à voir avec d'anciennes clés primaires.

    Soit le MCD suivant :
    personne -0,n----diriger----1,1- projet

    Tables :
    personne (prs_id, prs_nom...)
    projet (prj_id, prj_id_chef, prj_libelle...)

    Quelles personnes ne dirigent pas de projet ?
    => Celles dont l'identifiant ne figurent pas parmi les valeurs de la clé étrangère dans projet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT prs.prs_nom
    FROM personne prs
    LEFT OUTER JOIN projet prj ON prj.prj_id_chef = prs.prs_id
    WHERE prj.prj_id IS NULL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          SELECT a.*, b.*
          FROM t1 a LEFT OUTER JOIN t2 b 
                   ON (a.c1 = b.c1)
          WHERE b.c1 IS NULL;
    Req2 : idem que Req1 ?
    Hum... pas sûr !
    Je crains que le SGBD cherche d'abord les lignes de t2 (b) pour lesquelles la colonne c1 soit à NULL puis tente le rapprochement avec les lignes de t1 (a) ayant aussi c1 à NULL. Et comme NULL n'est en principe égal à rien, même pas à NULL, je crains que la requête ne retourne aucun résultat, même s'il y a effectivement des NULL dans c1 de t1 et de t2.
    À vérifier !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          SELECT a.*, b.*
          FROM t1 a LEFT OUTER JOIN t2 b 
                   ON (a.c1 = b.c1 AND a.c1 IS NULL);
    Req3 : ne retourne pas lignes ?
    Même comportement que la requête 2 je pense. Là aussi, c'est à vérifier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          SELECT a.*, b.*
          FROM t1 a LEFT OUTER JOIN t2 b 
                   ON (a.c1 = b.c1)
         WHERE a.c1 IS NULL;
    Req4 : retourne les lignes de t1 ayant a.c1 null, la jointure est inutile ?
    Oui je pense.

    Mais dans tout ça, comme je démontre avec le cas concret que j'ai donné plus haut, ton postulat de départ est faux :
    (on suppose que a.c1 clé étrangère optionnelle (et que peuvent y subsister d'anciennes clés de b n'existant plus (si c'est possible)) et b.c1 clé primaire):
    C'est plutôt le contraire.

    D'ailleurs, une clé étrangère optionnelle, c'est pas terrible du point de vue modélisation ! Il vaut mieux une colonne indiquant que la ligne est invalide ou supprimer la ligne.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 155
    Points : 74
    Points
    74
    Par défaut
    Eh bien il ne me reste qu'à vous remercier, tout ça me semble clair !
    Y en a qui veulent rajouter quelque chose ?

    Cordialement.

  7. #7
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Salut !

    J'ai aussi écrit un petit article là-dessus. Il est moche, mais il montre quelques exemples rigolos sur les NULL qu'il ne me semble pas avoir vu chez Cinephile (dont l'article est par contre vachement plus propre, clair et lisible) :
    http://pacmann.over-blog.com/article...-38449736.html

    Sinon pour aller un peu plus loin sur les remarques de Cinephile, il n'y a pas de question sur l'ordre d'exécution quand tu spécifies :
    (a.c1 = b.c1 AND b.c1 IS NULL)
    ou
    (a.c1 = b.c1 AND a.c1 IS NULL)

    Ce sont simplement deux prédicats qui ne seront jamais réalisé, carrément ni true ni false.
    Du coup, la ligne de gauche ressort quand même dans le resultset.

    Et du coup ce qui est amusant, c'est que même ta requête 3 retourne toutes les lignes de gauche.

    Au final, tu pourrais très bien écrire : LEFT OUTER JOIN ON 1 = 2

    (c'est ma photo)
    Paku, Paku !
    Pour les jeunes incultes : non, je ne suis pas un pokémon...

    Le pacblog : http://pacmann.over-blog.com/

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 155
    Points : 74
    Points
    74
    Par défaut
    D'ailleurs, une clé étrangère optionnelle, c'est pas terrible du point de vue modélisation ! Il vaut mieux une colonne indiquant que la ligne est invalide ou supprimer la ligne.
    Une table de jointure c'est sans doute aussi propre (?)
    On créé une ligne dans cette table quand il y a une jointure entre une ligne de a et une ligne de b.

Discussions similaires

  1. INNER JOIN avec ON et plusieurs conditions de jointure
    Par olysmar2 dans le forum Développement
    Réponses: 1
    Dernier message: 24/06/2015, 07h47
  2. Réponses: 7
    Dernier message: 13/12/2007, 13h32
  3. left outer join avec condition
    Par fisto dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 14/08/2007, 08h52
  4. Outer join avec condition OR
    Par Ujitsu dans le forum Langage SQL
    Réponses: 1
    Dernier message: 28/03/2007, 23h08
  5. INNER JOIN avec des données de sélection
    Par EK1_ dans le forum Langage SQL
    Réponses: 2
    Dernier message: 17/05/2006, 18h40

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