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 :

Ordre d'exécution dans une jointure externe


Sujet :

Langage SQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 51
    Points : 47
    Points
    47
    Par défaut Ordre d'exécution dans une jointure externe
    Bonjour à tous,

    Dans l'exemple suivant (tiré d'un article de Frédéric Brouard sur les jointures dans Developpez.com), dans quel ordre sont exécutées les clauses ??? Est-ce d'abord le "where" ou le "join" ???

    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2
    FROM TEST_JOIN1 TJ1
    LEFT OUTER JOIN TEST_JOIN2 TJ2 ON TJ1.COL1 = TJ2.COL1
    WHERE TJ1.COL2 = 'AA'
    Merci d'avance.

    Pero

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 801
    Points
    30 801
    Par défaut
    Quel que soit l'ordre d'exécution des clauses, cela n'aura aucune influence sur le résultat de cette requête
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 51
    Points : 47
    Points
    47
    Par défaut
    Dans ce cas quelle est la différence entre

    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2
    FROM TEST_JOIN1 TJ1
    LEFT OUTER JOIN TEST_JOIN2 TJ2
    ON TJ1.COL1 = TJ2.COL1 AND TJ1.COL2 = 'AA'
    et

    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2
    FROM TEST_JOIN1 TJ1
    LEFT OUTER JOIN TEST_JOIN2 TJ2
    ON TJ1.COL1 = TJ2.COL1
    WHERE TJ1.COL2 = 'AA'
    Merci.

  4. #4
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    A mon avis aucune, mais il y a un grosse différence entre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2 
    FROM TEST_JOIN1 TJ1 LEFT OUTER JOIN TEST_JOIN2 TJ2 ON TJ1.COL1 = TJ2.COL1 AND TJ2.COL2 = 'AA'
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2 
    FROM TEST_JOIN1 TJ1 LEFT OUTER JOIN TEST_JOIN2 TJ2 ON TJ1.COL1 = TJ2.COL1 
    WHERE TJ2.COL2 = 'AA'
    Puisque dans le deuxième cas l'aspect "externe" de la jointure est annulé.

    PS : utilise la balise code plutôt que quote.
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 51
    Points : 47
    Points
    47
    Par défaut
    Pourtant il y en a une !!! Va voir le point 2.4.3. Discussion sur la jointure externe de l'article de Frédéric Brouard sur http://sql.developpez.com/sqlaz/jointures/

    Je n'arrive pas à capter la différence entre le prédicat et la condition de jointure. Où, quand et comment se fait le prédicat et/ou la condition ???


    PS : Merci pour le tip du "code" ... je ne savais pas

  6. #6
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    As-tu fait le test tel que dans la page que tu indiques ?
    (je ne peux pas tester avant ce soir)
    Et ensuite avec mes requêtes ?
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 51
    Points : 47
    Points
    47
    Par défaut
    Les données de l'article sont exactes.

    Mais mis à part le résultat de ces requêtes, peux-tu m'expliquer la différence au niveau du traitement entre le TJ1.COL2 = 'AA' mis dans la clause where et mis dans la condition de jointure ???

    Merci.

  8. #8
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    Dans un LEFT OUTER JOIN, lorsque les conditions de jointures ne sont pas remplies pour une ligne de la table de gauche, on ajoute cette ligne au résultat malgré tout, les conditions du WHERE sont appliquées ensuite.
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 51
    Points : 47
    Points
    47
    Par défaut
    Voilà une réponse claire et précise.

    La clause "where" est appliquée après que les tables aient été jointes.

    Je trouvais qu'il y avait confusion possible après avoir lu l'article. Maintenant c'est très clair.

    Encore merci.

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    1 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 673
    Points : 1 775
    Points
    1 775
    Par défaut
    Je ne suis pas tout à fait d'accord avec toi Pedro :
    Citation Envoyé par Médiat
    A mon avis aucune, mais il y a un grosse différence entre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2 
    FROM TEST_JOIN1 TJ1 LEFT OUTER JOIN TEST_JOIN2 TJ2 ON TJ1.COL1 = TJ2.COL1 AND TJ2.COL2 = 'AA'
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT TJ1.COL1, TJ1.COL2, TJ2.COL1, TJ2.COL2 
    FROM TEST_JOIN1 TJ1 LEFT OUTER JOIN TEST_JOIN2 TJ2 ON TJ1.COL1 = TJ2.COL1 
    WHERE TJ2.COL2 = 'AA'
    Puisque dans le deuxième cas l'aspect "externe" de la jointure est annulé.
    Le problème porte sur la colonne de la table gauche de la jointure externe TJ1 et non TJ2.
    Ce qui change tout au problème (mais je ne remets pas en cause ce que tu affirmes Médiat ).

    D'autre part,
    Citation Envoyé par Pero
    La clause "where" est appliquée après que les tables aient été jointes
    Ton raisonnement est faux : de ce que j'ai compris voilà ce qu'il se passe :
    - requête 1/
    2 étapes :
    extraction des données de la TJ1, jointure "éventuelle" des lignes retournées avec les lignes de TJ2 suivant les conditions de la jointure
    filtre des données selon la clause WHERE

    - requête 2/
    extraction des données de la TJ1, jointure "éventuelle" des lignes retournées avec les lignes de TJ2 suivant les conditions de la jointure

    Conclusion : qu'est-ce qui te permet d'affirmer que les jointures sont effectuées AVANT les filtres ?

    Tu remarqueras que si l'on considère que les jointures sont effectuées APRES les filtres alors les résultats sont identiques.
    Modérateur des forums Oracle et Langage SQL
    Forum SQL : je n'interviens PAS plus de 4 fois dans une discussion car si c'est nécessaire cela prouve généralement que vous n'avez pas respecté : les règles du forum

  11. #11
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    Je n'ai pas la possibilité de tester immédiatement, mais il me semble que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TJ1       TJ2
    Id        Id    Code 
    1         1     A 
    2         1     NULL
    3         2     NULL
    4         3     B
    La requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM TJ1 LEFT OUTER JOIN TJ2 USING (Id)
    WHERE TJ2.Code IS NOT NULL
    Si le WHERE est effectuée avant on devrait trouver :
    1--> 1, A
    2--> NULL, NULL
    3--> 3, B
    4--> NULL, NULL

    Si le WHERE est effectué après on devrait trouver :
    1--> 1, A
    3--> 3, B

    Est-ce que tu peux faire l'essai ?
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

  12. #12
    Membre chevronné

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    1 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 673
    Points : 1 775
    Points
    1 775
    Par défaut
    Je n'ai pas très bien suivi ce que tu voulais me faire faire.

    Je pense que tu veux mettre en évidence que le WHERE est effectué AVANT ou APRES les jointures mais dans ce cas ton exemple ne semble pas construit correctement ou alors je n'arrive pas à le comprendre

    Donc j'ai "pondu" ça avec mon intuition :
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    CREATE TABLE TJ1 (
        ID INTEGER
    );
     
    CREATE TABLE TJ2 (
        ID INTEGER,
        CODE VARCHAR(20)
    );
     
     
    INSERT INTO TJ1 (ID)
    VALUES (1);
    INSERT INTO TJ1 (ID)
    VALUES (2);
    INSERT INTO TJ1 (ID)
    VALUES (3);
    INSERT INTO TJ1 (ID)
    VALUES (4);
     
    INSERT INTO TJ2 (ID, CODE)
    VALUES (1, 'A');
    INSERT INTO TJ2 (ID)
    VALUES (1);
    INSERT INTO TJ2 (ID)
    VALUES (2);
    INSERT INTO TJ2 (ID, CODE)
    VALUES (3, 'B');
    La requête suivante donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT *
    FROM TJ1
         LEFT OUTER JOIN TJ2 ON TJ1.ID = TJ2.ID
    WHERE TJ2.CODE IS NOT NULL;
    1 1 A
    3 3 B
    Conclusion : ????
    Modérateur des forums Oracle et Langage SQL
    Forum SQL : je n'interviens PAS plus de 4 fois dans une discussion car si c'est nécessaire cela prouve généralement que vous n'avez pas respecté : les règles du forum

  13. #13
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    D'après ce que j'ai expliqué, il me semble que cela démontre que le WHERE est effectué après...
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 51
    Points : 47
    Points
    47
    Par défaut
    : : Il me semble aussi Magnus ...

    D'après ta requête, on reçoit avant exécution de la clause where :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    1 1 A
    1 1 NULL
    2 2 NULL
    3 3 B
    4 NULL NULL
    Ensuite, après passage de la clause where :

    Ce n'est pas à cela que tu voulais en venir ... :

  15. #15
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    Je détaille :

    Si on applique le WHERE en premier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TJ1       TJ2 filtré 
    Id        Id    Code 
    1         1     A 
    2         
    3          
    4         3     B
    Ensuite la jointure externe Résultat :
    1, 1, A
    2, NULL, NULL
    3, 3, B
    4, NULL, NULL
    que l'on peut simuler avec la requête (testé avec ORACLE 9i):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT * 
    FROM TJ1 left outer join (SELECT * FROM TJ2 WHERE code IS NOT NULL) USING (Id)
    Si on applique la jointure externe en premier (ou seule) Résultat (testé avec ORACLE 9i):
    1, 1, A
    1, 1, NULL
    2, 2, NULL
    3, 3, B
    4, NULL, NULL
    Puis le WHERE, résultat :
    1, 1, A
    3, 3, B
    et c'est bien le résultat (testé avec ORACLE 9i) donné par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT * 
    FROM TJ1 LEFT OUTER JOIN TJ2 USING (Id) 
    WHERE TJ2.Code IS NOT NULL
    J'en déduis que dans cette dernière requête le WHERE est exécuté après la jointure.

    PS : je ne parle pas d'optimisation (qui risque de dépendre des moteurs et même du paramètrage), mais de fonctionnel, puisque c'était bien la question initiale.
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

  16. #16
    Membre chevronné

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    1 673
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 673
    Points : 1 775
    Points
    1 775
    Par défaut
    Je crois que l'on ne s'est pas compris.

    Je ne remet pas en question la conclusion de Pero mais je pense qu'avec l'exemple donné par SQLpro à propos des jointures externes on ne peut pas arriver à cette conclusion (en supposant que la clause WHERE est effectuée avant ou après les jointures on arrive au même résultat).

    En revanche, il est vrai qu'avec l'exemple de Médiat j'en arrive à la même conclusion que vous alors peu importe ce que je voulais dire quelques posts plus haut.
    Modérateur des forums Oracle et Langage SQL
    Forum SQL : je n'interviens PAS plus de 4 fois dans une discussion car si c'est nécessaire cela prouve généralement que vous n'avez pas respecté : les règles du forum

  17. #17
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 770
    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 770
    Points : 52 723
    Points
    52 723
    Billets dans le blog
    5
    Par défaut
    Vous dites tous n'importe quoi !!!

    En effet il est impossible de dire lequel des deux prédicat ON (du JOIN) ou la clause WHERE est effectué en premier et cela n'a AUCUNE importance.
    En effet ce sera le rôle de loptimiseur de commencer par le prédicats le plus intéressant à traiter en premier pour :
    - accélérer les traitements en activant les index
    - minimiser le nombre de lignes traitées.

    En conclusion, tantôt ce sera l'un, tantôt l'autre. Cela dépend des statistiques.

    Notez que :
    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
    19
    20
    21
    SELECT *
    FROM   TEST_JOIN1 TJ1 
           LEFT OUTER JOIN TEST_JOIN2 TJ2 
                ON TJ1.COL1 = TJ2.COL1 AND TJ2.COL2 = 'AA'
    -- pas de prédicat WHERE
    est équivalent à
     
    SELECT *
    FROM   TEST_JOIN1 TJ1 
           LEFT OUTER JOIN TEST_JOIN2 TJ2 
                ON TJ1.COL1 = TJ2.COL1
    WHERE  TJ2.COL2 = 'AA' OR TJ2.COL2 IS NULL
    -- prédicat WHERE et ON
    ou encore :
     
    SELECT *
    FROM   TEST_JOIN1 TJ1 
           CROSS JOIN TEST_JOIN2 TJ2 
    WHERE  (TJ1.COL1 = TJ2.COL1 OR   TJ2.COL1 IS NULL)
       AND (TJ2.COL2 = 'AA' OR TJ2.COL2 IS NULL)
    -- pas de prédicat ON
    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/ * * * * *

  18. #18
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    Citation Envoyé par SQLpro
    Vous dites tous n'importe quoi !!!
    Et toi tu ne lis pas les posts avant de les critiquer avec ton agressivité habituelle, voire injurieuse :

    PS : je ne parle pas d'optimisation (qui risque de dépendre des moteurs et même du paramètrage), mais de fonctionnel, puisque c'était bien la question initiale.
    et je constate que dans ta réfutation tu ne parles que d'optimisation.
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

Discussions similaires

  1. Réponses: 3
    Dernier message: 02/11/2011, 10h48
  2. Réponses: 4
    Dernier message: 22/06/2011, 08h49
  3. Limiter le nombre de correspondance dans une jointure externe ?
    Par Hervé Saladin dans le forum Développement
    Réponses: 5
    Dernier message: 26/11/2010, 11h27
  4. [Doctrine] Exécution d'une jointure externe
    Par christophetd dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 16/12/2009, 10h26
  5. Ordre des champs dans une table
    Par patapetz dans le forum Outils
    Réponses: 5
    Dernier message: 30/07/2003, 06h53

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