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

Développement SQL Server Discussion :

Jointures multiples en SQL


Sujet :

Développement SQL Server

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut Jointures multiples en SQL
    Bonjour,

    Suite à la migration d'une base ACCESS vers SQL Server, je suis un peu perdu avec le langage SQL (appris il y a une dizaine d'année, mais pas ou peu utilisé depuis), et les jointures multiples.

    J'ai créé la requête ACCESS suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT OCEAN_ADM_CELLULE.CELL_ID, OCEAN_ADM_MODRADIO.MRAD_REF
    FROM (OCEAN_ADM_SITE INNER JOIN OCEAN_ADM_BAIE ON OCEAN_ADM_SITE.SIT_ID = OCEAN_ADM_BAIE.SIT_ID) INNER JOIN (OCEAN_ADM_CELLULE INNER JOIN (OCEAN_ADM_CONFBAIE INNER JOIN OCEAN_ADM_MODRADIO ON (OCEAN_ADM_CONFBAIE.MRAD_ID = OCEAN_ADM_MODRADIO.MRAD_ID) AND (OCEAN_ADM_CONFBAIE.SYS_ID = OCEAN_ADM_MODRADIO.SYS_ID)) ON (OCEAN_ADM_CELLULE.SYS_ID = OCEAN_ADM_MODRADIO.SYS_ID) AND (OCEAN_ADM_CELLULE.CTR_ID = OCEAN_ADM_MODRADIO.CTR_ID)) ON OCEAN_ADM_BAIE.BAI_ID = OCEAN_ADM_CONFBAIE.BAI_ID
    WHERE (((OCEAN_ADM_CELLULE.CTR_ID)=6))
    GROUP BY OCEAN_ADM_CELLULE.CELL_ID, OCEAN_ADM_MODRADIO.MRAD_REF;
    Nom : Requête.png
Affichages : 3964
Taille : 75,2 Ko

    Comment traduire cela en SQL pour SQL Server ?

    En relisant mes cours sur le language SQL, je comprend bien comment créer une jointure entre 2 tables.
    Mais lorsque il y a plusieurs jointures vers la même table qui elle même comporte plusieurs jointures vers une autre table, là je suis perdu.
    Y a-t-il une astuce pour faciliter l'écriture du code ?


    Merci pour votre aide
    Kennely

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    globalement, les "astuces" sont toujours les même et somme toute assez basiques :
    1/ indentation
    2/ utilisation des alias
    3/ suppression du superflu (comme les parenthéses dans votre cas)

    ce qui donne avec votre requete :

    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
     
    SELECT 
    		Cel.CELL_ID
    	,	Mo.MRAD_REF
    FROM		OCEAN_ADM_SITE sit
    INNER JOIN	OCEAN_ADM_BAIE bai
    		ON		sit.SIT_ID = bai.SIT_ID
    INNER JOIN	OCEAN_ADM_CELLULE Cel
    			INNER JOIN OCEAN_ADM_CONFBAIE conf
    						INNER JOIN OCEAN_ADM_MODRADIO Mo
    								ON			conf.MRAD_ID = Mo.MRAD_ID 
    								AND			conf.SYS_ID = Mo.SYS_ID 
    					ON		Cel.SYS_ID = Mo.SYS_ID 
    					AND		Cel.CTR_ID = Mo.CTR_ID 
    		ON		bai.BAI_ID = conf.BAI_ID
    WHERE	Cel.CTR_ID=6
    GROUP BY 
    			Cel.CELL_ID
    		,	Mo.MRAD_REF
    ;

  3. #3
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2003
    Messages : 733
    Points : 1 668
    Points
    1 668
    Billets dans le blog
    8
    Par défaut
    Cette syntaxe de Microsof Access n'a plus cours et, à ma connaissance n'a même jamais eu cours sous SQL Server ! Il faut respecter désormais la norme SQL

    Sous SQL Server, votre requête doit être réécrite comme suit :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT OCEAN_ADM_CELLULE.CELL_ID, OCEAN_ADM_MODRADIO.MRAD_REF
    FROM OCEAN_ADM_SITE 
    INNER JOIN OCEAN_ADM_BAIE 
      ON OCEAN_ADM_SITE.SIT_ID = OCEAN_ADM_BAIE.SIT_ID
    INNER JOIN OCEAN_ADM_CONFBAIE 
      ON OCEAN_ADM_BAIE.BAI_ID = OCEAN_ADM_CONFBAIE.BAI_ID 	
    INNER JOIN OCEAN_ADM_MODRADIO 
      ON  OCEAN_ADM_CONFBAIE.MRAD_ID = OCEAN_ADM_MODRADIO.MRAD_ID 
      AND OCEAN_ADM_CONFBAIE.SYS_ID = OCEAN_ADM_MODRADIO.SYS_ID	
    INNER JOIN OCEAN_ADM_CELLULE 
      ON  OCEAN_ADM_CELLULE.SYS_ID = OCEAN_ADM_MODRADIO.SYS_ID
      AND OCEAN_ADM_CELLULE.CTR_ID = OCEAN_ADM_MODRADIO.CTR_ID
    WHERE OCEAN_ADM_CELLULE.CTR_ID = 6
    GROUP BY OCEAN_ADM_CELLULE.CELL_ID, OCEAN_ADM_MODRADIO.MRAD_REF;

    A+

    PS : Je n'avais pas vu la réponse de aieeeuuuuu !
    "Une idée mal écrite est une idée fausse !"
    http://hamid-mira.blogspot.com

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 759
    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 759
    Points : 52 538
    Points
    52 538
    Billets dans le blog
    5
    Par défaut
    Access rajoute des tonnes de parenthèses totalement farfelues et pour certaines (notamment jointures) totalement incompréhensible. Débarrassez vous de l'écriture automatique des requêtes via le gadget visuel d'accès et écrivez vos propres requêtes sous forme textuelle !

    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/ * * * * *

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut Merci pour vos réponses
    Merci pour vos réponses.
    Je suis d'accord, ACCESS rajoute des tonnes de parenthèses et utilise son propre code SQL.

    OK pour les alias.
    J'ai aussi remarqué que l'on peux utiliser le JOIN sans le INNER
    Ce qui me perturbe dans vos réponses c'est que aieeeuuuuu imbrique les INNER JOIN et met ensuite les condition ON, alors que ce n'est pas le cas de hmira.
    Les 2 codes sont équivalents ?
    Kennely

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par kennely Voir le message
    J'ai aussi remarqué que l'on peux utiliser le JOIN sans le INNER
    En effet, INNER est facultatif (par défaut).

    Citation Envoyé par kennely Voir le message
    Ce qui me perturbe dans vos réponses c'est que aieeeuuuuu imbrique les INNER JOIN et met ensuite les condition ON, alors que ce n'est pas le cas de hmira.
    Les 2 codes sont équivalents ?
    J'ai en effet gardé la structure initiale de votre requete.
    Dans le cas de jointures internes uniquement, c'est équivalent, et je trouve l'écriture d'hmira bien plus lisible (notamment car la condition de jointure suit directement la table jointe...). Cette écriture est d'ailleurs nettement plus courante, et de surcroit, rien ne vous empêche d'indenter les jointures pour une meilleur lisibilité de l'arborescence, sans pour autant imbriquer les jointures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT ...
    FROM CLIENT C
    INNER JOIN COMMANDE C
        ON C.cli_id = C.cli_id
                INNER JOIN COMMANDE_DETAIL CD
                    ON CD.cmd_id = C.cmd_id
    INNER JOIN PAIEMENT P
        ON P.cli_id = C.cli_id
                INNER JOIN PAIEMENT_DETAIL PD
                    ON PD.pai_id = P.pai_id
    L'imbrication des jointures devient cependant utile en cas de jointure externe. Si dans l'exemple ci dessus, vous supposez qu'un client peut ne pas avoir de commande et qu'il peut ne pas avoir de paiement (mais que vous voulez malgré tout garder ces clients dans le résultat de la requête) vous pouvez passer toutes les jointures en jointure externe, ou bien écrire comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT ...
    FROM CLIENT C
    LEFT JOIN COMMANDE C
                INNER JOIN COMMANDE_DETAIL CD
                    ON CD.cmd_id = C.cmd_id
        ON C.cli_id = C.cli_id
    LEFT JOIN PAIEMENT P
                INNER JOIN PAIEMENT_DETAIL PD
                    ON PD.pai_id = P.pai_id
        ON P.cli_id = C.cli_id

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut
    aieeeuuuuu, merci pour ces précisions.
    En effet, je trourve aussi le code d'hmira plus lisible.
    C'est ACCESS qui a créé ces imbrications.

    Grâce à vos explications (à tout les deux), j'ai pu créer ma requête que j'ai utilisé dans une requête mise à jour avec une instruction CASE.
    Pour me remettre dans le bain, pourriez-vous me conseiller un livre de référence sur le code SQL ?
    Kennely

  8. #8
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    INNER comme OUTER sont implicites, et peut être supprimés :

    INNER JOIN = JOIN tout court

    LEFT OUTER JOIN = LEFT JOIN tout court
    RIGHT OUTER JOIN = RIGHT JOIN tout court

    Cependant, c'est plus clair avec la syntaxe complète.

    Quand tu vas chez le boulanger, tu dis "bonjour, je voudrais une baguette s'il vous plait" et non "tu m'en donnes une ?"
    Que ce soit avec la boulangère ou avec SQL Server, la syntaxe complète évitera quelques insultes.

    Ensuite, pour en revenir à la requête initiale d'Access, sans parler de l'utilité ou non des parenthèses, avez-vous testé la requête dans SQL Server ?
    Car en la lisant en diagonale, pour moi elle devrait fonctionner.

    Elle est moche, certes, mais elle doit marcher.

    Et pour répondre à hmira, la syntaxe "farfelue" d'Access est tout à fait normée, et même si Access pète les plombs en obligeant le moteur à faire des jointures d'une manière étrange, cette syntaxe est parfaitement normée et peut sauver la vie avec les jointures ouvertes.

    Par exemple :
    Exemple pondu à l'arrache, il n'est pas ultra explicite, d'autant que la requête peut facilement être écrite autrement.
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    select *
    from fournisseur
    left outer join (
      commande
      inner join produit on produit.id = commande.produit_id
    ) on fournisseur.id = produit.fournisseur_id

    Ça marche parfaitement, et le résultat ne sera pas le même avec une autre syntaxe (à moins de tout réécrire la requête, notamment en changement l'ordre des jointures, ce qui n'est pas toujours possible)
    On ne jouit bien que de ce qu’on partage.

  9. #9
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par kennely Voir le message
    Pour me remettre dans le bain, pourriez-vous me conseiller un livre de référence sur le code SQL ?
    Celui de SQLpro

    Sinon, commence déjà par lire son blog.
    http://blog.developpez.com/sqlpro/
    On ne jouit bien que de ce qu’on partage.

  10. #10
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2003
    Messages : 733
    Points : 1 668
    Points
    1 668
    Billets dans le blog
    8
    Par défaut
    Contrairement à la syntaxe hiérarchique avec indentation utilisé par aieeeuuuuu, où les opérandes de chacune des jointures sont expressément délimités, dans les écritures habituelles des jointures tel celui de la requête que j'ai donnée, il faut être plus vigilant. Il ne faut surtout pas comprendre qu'une jointure de niveau N est une jointure entre la table N et la table N+1, c'est complètement faux !

    Exemple
    Soit la requête ci-dessous établissant des jointures entre 3 tables ou requête (Table_1, Table_2 et Table_3) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT *
    FROM Table_1 
    INNER JOIN Table_2   -- 1ère jointure
     ON ....  
    INNER JOIN Table_3   -- 2ème jointure 
      ON ....

    La 2ème jointure INNER JOIN Table_3 n'est pas comme beaucoup le pensent à tort, une jointure entre Table_2 et Table_3 ! Ce n'est pas du tout cela.

    La 2ème jointure est une jointure entre une relation R et Table_3. La relation R étant constituée comme la jointure entre les 2 tables Table_1 et Table_2. Par ailleurs, et pour preuve, vous pouvez dans la clause ON de la 2ème jointure référencer aussi bien des colonnes de la Table_3, de la Table_2 ou même de la Table_1.

    C'est comme si schématiquement on écrivait ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (Table_1 JOIN Table_2) JOIN Table_3
    C'est important de comprendre cela. C'est ce qui permet d'anticiper le résultat ou l'impact, par exemple d'un LEFT JOINT au milieu d'une série de JOIN entre plusieurs tables. En effet, d'aucuns peuvent être surpris du résultat d'une requête complexe sans comprendre le pourquoi du comment !

    Note : Pour la simplification de l'écriture symbolique, et dans tout ce qui suit, j'ai volontairement omis les clauses de jointure ON ; il ne s'agit donc pas d'un produit cartésien CROSS JOIN.

    Les opérateurs ensemblistes JOIN (INNER JOIN ou LEFT OUTER JOIN etc.), appliqués à l'ensemble des relations, sont des Lois de compositions internes. Elles concourent au fondement de l'Algèbre relationnelle.

    Ces lois (ou opérateurs ensemblistes JOIN) sont bien évidemment associatives, mais pas toujours commutatives.

    Elles sont associatives puisque nous avons l'équivalence entre les deux expressions ensemblistes, comme le montre l'exemple ci-dessous :

    (Table_1 JOIN Table_2) JOIN Table_3 est équivalente (identique à) à Table_1 JOIN (Table_2 JOIN Table_3)Dans l'écriture ci-dessus, j’ai volontairement omis les clauses de jointure ON ; il ne s'agit donc pas d'un produit cartésien CROSS JOIN.

    Les opérateurs ensemblistes JOIN ne sont pas toujours commutatifs, en d'autres termes :

    Table_1 JOIN Table_2 n'est pas toujours équivalente à Table_2 JOIN Table_1 (ça l'est parfois, pour les jointures internes, mais pas toujours !).


    A+
    "Une idée mal écrite est une idée fausse !"
    http://hamid-mira.blogspot.com

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Elle est moche, certes, mais elle doit marcher.
    Oui effectivement, elle donne bien le résultat attendu.
    Kennely

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Celui de SQLpro

    Sinon, commence déjà par lire son blog.
    http://blog.developpez.com/sqlpro/
    OK Merci
    Kennely

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par hmira Voir le message
    Il ne faut surtout pas comprendre qu'une jointure de niveau N est une jointure entre la table N et la table N+1, c'est complètement faux !
    Je crois bien que c'était mon cas.

    Citation Envoyé par hmira Voir le message
    Exemple
    Soit la requête ci-dessous établissant des jointures entre 3 tables ou requête (Table_1, Table_2 et Table_3) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT *
    FROM Table_1 
    INNER JOIN Table_2   -- 1ère jointure
     ON ....  
    INNER JOIN Table_3   -- 2ème jointure 
      ON ....

    La 2ème jointure INNER JOIN Table_3 n'est pas comme beaucoup le pensent à tort, une jointure entre Table_2 et Table_3 ! Ce n'est pas du tout cela.

    La 2ème jointure est une jointure entre une relation R et Table_3. La relation R étant constituée comme la jointure entre les 2 tables Table_1 et Table_2. Par ailleurs, et pour preuve, vous pouvez dans la clause ON de la 2ème jointure référencer aussi bien des colonnes de la Table_3, de la Table_2 ou même de la Table_1.
    Là j'ai un peu de mal à vous suivre, vous dîtes :
    La 2ème jointure est une jointure entre une relation R et Table_3.
    La relation R étant constituée, comme la jointure, entre les 2 tables, Table_1 et Table_2.

    Je comprends donc que :

    1- La 2ème jointure est une jointure entre une relation R et Table_3.
    2 - La relation R est constituée entre les 2 tables, Table_1 et Table_2.
    3 - La jointure (laquelle ?) est constituée entre les 2 tables, Table_1 et Table_2

    Pouvez-vous donner un exemple détaillé, SVP ?
    J'ai bien conscience qu'il est très important de bien maitriser cela pour réaliser des requêtes complexes, et je vais en avoir besoin très prochainement.

    Le problème avec ACCESS, c'est que l'on s'habitue assez facilement à utiliser l'interface graphique, sans se soucier du code généré.
    Kennely

  14. #14
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par hmira Voir le message
    (Table_1 JOIN Table_2) JOIN Table_3 est équivalente (identique à) à Table_1 JOIN (Table_2 JOIN Table_3)
    En cas de INNER JOIN, je veux bien te croire, mais en cas de mélange entre jointure interne et jointure externe, je m'insurge, c'est faux !

    Exemple :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    select *
    from table_1 t1
    left outer join table_2 t2 on t2.id = t1.id
    inner join table_3 t3 on t3.id = t2.id;
     
    select *
    from table_1 t1
    left outer join (table_2 t2
    inner join table_3 t3 on t3.id = t2.id)  on t2.id = t1.id;

    Données d'exemple :
    Code sql : 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
    28
    29
    30
    31
     
    create table table_1
    (
    	id int primary key,
    	nom varchar(50) not null
    );
     
    create table table_2
    (
    	id int primary key,
    	nom varchar(50) not null
    );
     
    create table table_3
    (
    	id int primary key,
    	nom varchar(50) not null
    );
     
    insert into table_1 (id, nom) values (1, 'Ligne 1');
    insert into table_1 (id, nom) values (2, 'Ligne 2');
    insert into table_1 (id, nom) values (3, 'Ligne 3');
    insert into table_1 (id, nom) values (4, 'Ligne 4');
     
    insert into table_2 (id, nom) values (1, 'Ligne 1');
    insert into table_2 (id, nom) values (3, 'Ligne 3');
    insert into table_2 (id, nom) values (4, 'Ligne 4');
     
    insert into table_3 (id, nom) values (1, 'Ligne 1');
    insert into table_3 (id, nom) values (2, 'Ligne 2');
    insert into table_3 (id, nom) values (4, 'Ligne 4');

    Et mise à part une réécriture complète de la requête (en changeant l'ordre des jointures et leur type) on ne peut pas retomber sur nos pieds sans parenthèses.
    En effet, cela ne revient pas non plus à avoir des jointures externes en cascade :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT *
    FROM table_1 t1
    LEFT OUTER JOIN table_2 t2 ON t2.id = t1.id
    LEFT OUTER JOIN table_3 t3 ON t3.id = t2.id;

    Le seule moyen de se passer des parenthèses, c'est de rejeter la première jointure en dernier et d'inverser son sens, et la requête devient illisible (seul un autiste est en mesure de comprendre un RIGHT JOIN) :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    select *
    from table_2 t2
    inner join table_3 t3 on t3.id = t2.id
    right outer join table_1 t1 on t1.id = t2.id;

    Sauf que si on avait eu une couche supplémentaire de jointure derrière, on n'aurait pas forcément pu.

    Donc les parenthèses même si Access en colle partout inutilement, ont une parfaite raison d'exister.
    On ne jouit bien que de ce qu’on partage.

  15. #15
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2003
    Messages : 733
    Points : 1 668
    Points
    1 668
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par kennely Voir le message
    Je comprends donc que :

    1- La 2ème jointure est une jointure entre une relation R et Table_3.
    2 - La relation R est constituée entre les 2 tables, Table_1 et Table_2.
    3 - La jointure (laquelle ?) est constituée entre les 2 tables, Table_1 et Table_2

    Vous n'avez pas lu attentivement mes explications ! Dans l'exemple simple que j'ai donné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    R = Table_1 JOIN Table_2  -- 1ère jointure 
    puis, 
    R JOIN Table_3         -- 2ème jointure
    La 2ème jointure est donc une jointure entre R et Table_3.


    Citation Envoyé par kennely Voir le message
    Pouvez-vous donner un exemple détaillé, SVP ?
    Toutes les requêtes construites selon cette syntaxe sont des exemples ! y compris la requête de transformation ACCESS vers SQL Server que je vous ai fournie ci-haut. Je peux donc ainsi vous donner une infinité d'exemples !
    Mais, au delà des exemples, ce que je voulais insuffler, au travers les jointures, ce sont des structures mathématiques afférentes, une véritable théorie que nous avons bâtie, celle de l'Algèbre relationnelle, elle-même dérivée d'une autre théorie bien plus large, celle de la Théorie des ensembles.

    A+
    "Une idée mal écrite est une idée fausse !"
    http://hamid-mira.blogspot.com

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par hmira Voir le message
    Vous n'avez pas lu attentivement mes explications !
    Non je n'avais pas compris vos explications.

    Merci pour ces éclaircissement
    Kennely

  17. #17
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 21
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par kennely Voir le message
    aieeeuuuuu,
    Pour me remettre dans le bain, pourriez-vous me conseiller un livre de référence sur le code SQL ?

    Aieeeuuuuu,

    Je n'avais pas vu à qui j'avais à faire.
    Je vais acheter votre livre !
    Kennely

  18. #18
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2003
    Messages : 733
    Points : 1 668
    Points
    1 668
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    En cas de INNER JOIN, je veux bien te croire, mais en cas de mélange entre jointure interne et jointure externe, je m'insurge, c'est faux !
    Oui, tu as bien raison d'apporter ces précisions et ces éclairages.

    Quand je parlais de commutativité ou d'associativié c'est toujours pour loi de composition interne donnée ( INNER JOIN ou bien OUTER JOIN ou bien ... ), donc jamais de mélange (sinon, on n'est plus dans le cadre d'une loi de composition interne), ceci dit tu as bien eu raison de le préciser, en donnant un exemple concret, et de montrer qu'en cas de mélange entre jointure interne et externe, l'associativité (ou plutôt la manière d'agencer les parenthèses) fait que le résultat ne sera pas toujours le même. Ce n'était pas évident. Merci.

    En utilisant la notation avec des parenthèses on peut sauf erreur de ma part (ou contre exemple trouvé !) affirmer les équivalences ci-dessous relatives au caractère associatif de chacun des opérateurs ensemblistes ci-après :
    INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN et CROSS JOIN


    Cas 1 : INNER JOIN
    Les 2 requêtes ci-dessous sont équivalentes

    Code SQL : 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
    --  ( Table_1 inner_join  Table_2 )  inner_join  Table_3
    SELECT table_1.*  , Table_2.*, table_3.*   
      FROM ( 
            Table_1  
            INNER JOIN  Table_2 
    	    ON  Table_2.id = Table_1.id   
    		) 
    INNER JOIN  Table_3 
    ON Table_3.id = Table_2.Id 
     
     
    --   Table_1 left_join ( Table_2 left_join Table_3 ) 
    SELECT table_1.*  , Table_2.*, table_3.*   
      FROM Table_1   
    INNER JOIN (
        Table_2 
        INNER JOIN Table_3 
         ON Table_3.id = Table_2.Id 
    	 ) 
    ON  Table_2.id = Table_1.id

    Cas 2 : LEFT OUTER JOIN
    Les 2 requêtes ci-dessous sont équivalentes

    Code SQL : 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
    --  ( Table_1 left_join Table_2 )  left_join  Table_3
    SELECT table_1.*  , Table_2.*, table_3.*   
      from ( Table_1  
             left outer join Table_2 
    	    ON  Table_2.id = Table_1.id   ) 
    LEFT OUTER JOIN Table_3 
    ON Table_3.id = Table_2.Id 
     
     
    -- Table_1 left_join ( Table_2 left_join  Table_3 ) 
    SELECT table_1.*  , Table_2.*, table_3.*   
      FROM Table_1   
    LEFT OUTER JOIN (
        Table_2 
        LEFT OUTER JOIN Table_3 
         ON Table_3.id = Table_2.Id 
    	 ) 
    ON  Table_2.id = Table_1.id


    Cas 3 : RIGHT OUTER JOIN
    Les 2 requêtes ci-dessous sont équivalentes

    Code SQL : 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
    --   ( Table_1 right_join Table_2 ) right_join Table_3
    SELECT table_1.*  , Table_2.*, table_3.*   
      from ( Table_1  
             RIGHT OUTER JOIN Table_2 
    	    ON  Table_2.id = Table_1.id   ) 
    RIGHT OUTER JOIN Table_3 
         ON Table_3.id = Table_2.Id 
     
    --   Table_1 right_outer_join  (Table_2 left_join  Table_3) 
    SELECT table_1.*  , Table_2.*, table_3.*   
      FROM Table_1   
    RIGHT OUTER JOIN (
        Table_2 
        RIGHT OUTER JOIN Table_3 
         ON Table_3.id = Table_2.Id 
    	 ) 
    ON  Table_2.id = Table_1.id

    Cas 4 : CROSS JOIN
    Les 2 requêtes ci-dessous sont équivalente :

    Code 4SQL' : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    --  ( Table_1 cross_join Table_2 )  cross_join Table_3
    SELECT table_1.*  , Table_2.*, table_3.*   
      FROM (
             Table_1  
             CROSS JOIN Table_2 
    	    ) 
    CROSS JOIN  Table_3 
     
    --   Table_1 cross_join ( Table_2 cross_join Table_3) 
    SELECT table_1.*  , Table_2.*, table_3.*   
       FROM Table_1   
    CROSS JOIN (
                 Table_2 
                 CROSS JOIN Table_3 
    	       )

    Pour les autres opérateur ensemblistes ou autres combinaisons, il faut rester très prudent quant à l'affirmation ou non de leur caractère associatif.


    Citation Envoyé par StringBuilder Voir le message
    Donc les parenthèses même si Access en colle partout inutilement, ont une parfaite raison d'exister.
    Oui, mais on peut s'en passer.
    Chacun a ses habitudes pour exprimer les requêtes, mais je pense qu'on peut toujours trouver l'équivalence en SQL "normalisé" sinon le langage SQL normalisé serait incomplet, éventualité à laquelle je n'ose y croire !

    A+
    "Une idée mal écrite est une idée fausse !"
    http://hamid-mira.blogspot.com

Discussions similaires

  1. Requete SQL avec jointure multiple
    Par kissskoool dans le forum Langage SQL
    Réponses: 5
    Dernier message: 20/01/2008, 01h07
  2. [SQL 2000] Optimisation requête avec jointure multiple
    Par zooffy dans le forum Développement
    Réponses: 5
    Dernier message: 18/09/2007, 15h38
  3. [SQL 2000] Optimisation requête avec jointure multiple
    Par zooffy dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 18/09/2007, 15h38
  4. Jointures externes multiples en SQL ACCESS
    Par philnext dans le forum Langage SQL
    Réponses: 3
    Dernier message: 08/09/2007, 16h53
  5. [PostGre SQL] Jointure multiples impossible
    Par Montaigne dans le forum Langage SQL
    Réponses: 8
    Dernier message: 27/04/2006, 10h20

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