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 :

Question générale : liens entre tables d'une BDD et jointures SQL


Sujet :

Langage SQL

  1. #1
    Membre confirmé
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Décembre 2022
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Décembre 2022
    Messages : 76
    Par défaut Question générale : liens entre tables d'une BDD et jointures SQL
    Bonjour à tous,

    Je pense que je vais me faire passer pour un charlot avec ma question.
    Mais je tente... quand même...

    Question générale juste pour comprendre le mécanisme de fonctionnement.

    En gros, j'ai une BDD Access faite d'une table principale et de tables satellites avec des liens (plusieurs - un) avec la table principale.
    Je fais une requête SQL simple dessus avec un WHERE TablePrincipale.ChampX = TableSatellite.ChampY AND TableSatellite.ChampY='Valeur'

    Pourquoi faut-il préciser dans le WHERE le lien de la TablePrincipale avec la TableSatellite (TablePrincipale.ChampX = TableSatellite.ChampY) ?
    C'est pas implicite pour lui ? J'ai déjà créé mes liens entre les tables dans Access. C'est déjà dans ma base de données. La requête ne prend pas en compte les liens créés entre les tables ? Il faut tout lui repréciser ?

    Je ne comprends pas cela...

    Merci de votre aide.

  2. #2
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 315
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 315
    Billets dans le blog
    17
    Par défaut
    Je ne connais pas Access, mais je dirais :

    Soit parce que tu as dans tes 2 tables des colonnes du même nom, préciser la table permet ainsi de lever tout ambiguïté

    Soit parce que Access a toujours besoin de qualifier pleinement la colonne

  3. #3
    Membre Expert
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 172
    Par défaut
    Bonjour,

    Alors normalement les jointures se précisent dans la clause JOIN. La clause WHERE sert à filtrer les données une fois jointes. C'est conceptuellement plus facile à comprendre comme ça.
    Maintenant pour répondre à ta question, pourquoi les jointures ne se font pas toutes seules. Premièrement, pour des raisons évidentes de clarté. Sans les jointures, il faudrait rechercher la déclaration des tables pour voir quelles sont les clés primaires et étrangères définies. Pas évident si ta requête implique une dizaine de tables par exemple. Ensuite, rien ne garantit que les liens entre les différentes tables aient été faits correctement. Enfin, tu peux très bien vouloir faire une jointure sans forcément associer toutes les colonnes des clés définies.

  4. #4
    Membre confirmé
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Décembre 2022
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Décembre 2022
    Messages : 76
    Par défaut
    Bonsoir Vanagreg,

    Donc si je comprends bien, il faut lui indiquer les jointures et je comprends mieux pourquoi maintenant.

    Si je mets les jointures dans un WHERE tout simple, ça fonctionne bien. Je l'ai testé.
    Mais si je te suis, c'est pas très propre comme écriture de code. C'est cela ?

    Du coup, si je veux être plus rigoureux dans le code (ce que je souhaite), je dois faire des inner join pour chaque jointure et mettre les valeurs filtres dans le WHERE ?
    C'est plus propre comme codage ?

    Et en terme de temps d'exécution de requête, c'est la même chose ?
    Car j'ai cru lire en me documentant qu'il faisait d'abord une projection complète avec les INNER JOIN puis appliquait les filtres dessus.

    En tout cas, merci car on apprend beaucoup ici.

  5. #5
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 599
    Billets dans le blog
    10
    Par défaut
    Les performances peuvent être meilleurs avec JOIN :

    Avec certains optimiseurs, faire la jointure dans la restriction (dans le WHERE) pénalise les performances, car la restriction est appliquée après avoir fait le produit cartésien, alors que la clause JOIN permet de faire d'abord la jointure puis la restriction.
    Cela étant dit, le plus souvent, ça ne change rien aux performances, mais il est plus clair de séparer ce qui est du ressort de la jointure de ce qui est du ressort de la restriction, ce sont bien deux notions fonctionnellement très différentes.

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 997
    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 997
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par Krys9292 Voir le message
    Bonjour à tous,

    Je pense que je vais me faire passer pour un charlot avec ma question.
    Mais je tente... quand même...

    Question générale juste pour comprendre le mécanisme de fonctionnement.

    En gros, j'ai une BDD Access faite d'une table principale et de tables satellites avec des liens (plusieurs - un) avec la table principale.
    La notion de "line" n'existe pas dans l'univers des bases de données relationnelles. C'est même le contraire, c'est l'absence de lien qui permet aux SGBD Relationnel d'être bien supérieur à tout autre systèmes de SGBD... Ce que vous appelez lien est sans doute une clef étrangère, gérée par une intégrité référentielle (contraintes) pour éviter que des lignes d'une table fille référençant une table mère ne deviennet orphelines de la référence.

    Un exemple simple avec CLIENT et FACTURE.

    Un facture sans client c'est inconcevable. Il faut donc référencer le client afférent à une facture. Voici comment l'on s'y prend en SQL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE TABLE T_CLIENT_CLI 
    (CLI_ID         INT PRIMARY KEY,
     CLI_NOM        VARCHAR(32),
     CLI_CREATION   DATE);
     
    CREATE TABLE T_FACTURE_FAC
    (FAC_ID         INT PRIMARY KEY,
     CLI_ID         INT FOREIGN KEY REFERENCES T_CLIENT_CLI (CLI_ID), --> les valeurs de ,cette information doivent être prise dans la table des clients
     FAC_DATE       DATE,
     FAC_MONTANT    DECIMAL(16,2),
     FAC_LIBELLE    VARCHAR(256));
    Ainsi il ne sera pas possible de supprimer un client ayant des factures...

    Quant à la jointure c'est une opération de rapprochement de données basées sur n'importe quelle colonnes d'au moins deux tables...

    Voici trois exemples de jointures :

    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
    -- les factures émise après la création du client n°999
    SELECT F.*
    FROM   T_FACTURE_FAC  AS F
           JOIN T_CLIENT_CLI AS C
              ON FAC_DATE > CLI_CREATION
    WHERE  F.CLI_ID = 999;
     
    -- les factures dont le libellé contient un nom de client 
    SELECT F.*
    FROM   T_FACTURE_FAC  AS F
           JOIN T_CLIENT_CLI AS C
              ON FAC_LIBELLE LIKE CONCAT('%', CLI_NOM, '%');
     
    -- les factures du client 133
    SELECT F.*
    FROM   T_FACTURE_FAC  AS F
           JOIN T_CLIENT_CLI AS C
              ON F.CLI_ID = C.CLI_ID
    WHERE  C.CLI_ID = 133;
    Comme vous le constatez une seule des 3 requêtes base sa jointure sur la clef étrangère en rapport à la clé primaire de référence...

    Autrement dit, une jointure n'a pas de "line génétique" avec l'intégrité référentielle ! Et heureusement....
    Autrefois dans les based e donnés en Cobol c'était le cas et on était très limité pour l'interrogation des données.... (années 50 à 70 c'est à dire avant l'arrivée des SGBD Relationnels.)




    Je fais une requête SQL simple dessus avec un WHERE TablePrincipale.ChampX = TableSatellite.ChampY AND TableSatellite.ChampY='Valeur'

    Pourquoi faut-il préciser dans le WHERE le lien de la TablePrincipale avec la TableSatellite (TablePrincipale.ChampX = TableSatellite.ChampY) ?
    C'est pas implicite pour lui ? J'ai déjà créé mes liens entre les tables dans Access. C'est déjà dans ma base de données. La requête ne prend pas en compte les liens créés entre les tables ? Il faut tout lui repréciser ?
    Enfin les jointure ne doivent pas se faire ans le WHERE. Je m'étonne encore que l'on apprenne cette imbécilité !

    A +

    PS lisez mon cours sur le SQL et notamment : https://sqlpro.developpez.com/cours/...ointures/#LIII
    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/ * * * * *

  7. #7
    Membre confirmé
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Décembre 2022
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Décembre 2022
    Messages : 76
    Par défaut
    Je te remercie SQLpro pour avoir pris ton temps pour m'expliquer tout cela.
    Je l'ai relu plusieurs fois pour bien tout saisir.

    Effectivement, je n'allais pas dans le bon sens. Je n'avais pas saisi la philosophie du truc.
    En plus tes codes m'ont donné des idées sur les possibilités du coup très vastes.

    Quant au WHERE... c'est vrai que c'est dommage de retrouver cela sur certains tutos.
    Car en fait, ça oriente mal les gens comme moi qui apprennent, à d'une part ne pas pouvoir comprendre les concepts qui se cachent derrière (c'est important), d'autre part à adopter des mauvaises pratiques de développement, et au final à adopter le comportement de je ne comprends rien de ce que j'écris mais du moment que "ça marche"...

    En tout cas, merci encore.

    Du coup, je me suis documenté sur ces sujets.
    Et j'ai même repéré avec tes explications certains tutos vraiment pas "propres".

    Depuis, j'ai réussi à enchâsser plusieurs INNER JOIN les uns sur les autres. Et ça marche bien. Et effectivement, c'est rapide.

    Juste que je sèche maintenant sur un problème. J'ai une table qui est jointe plusieurs fois à différents champs de ma table principale mais qui prend des valeurs différentes.
    Du coup, quand j'écris les INNER JOIN les uns sur les autres, il ne comprend plus.
    J'imagine qu'il doit se dire, j'ai une relation entre la petite table et la table principale, puis une autre entre cette même petite table et la table principale mais la relation différente... Et il comprend plus, ça le bloque car pour lui c'es incompatible...
    Je ne sais pas, mais avec mes recherches, j'avais juste une idée. Faire deux requêtes séparées et les associer... Je ne sais pas si c'est possible de faire par exemple un SELECT sur deux SELECT

  8. #8
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 599
    Billets dans le blog
    10
    Par défaut
    Quand on a besoin d'utiliser plusieurs fois la même table dans une requête, il suffit de lui donner des noms différents en utilisant des alias de tables comme ci-dessous :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select T1A.Col1
         , T1A.Col2
         , T1B.Colx
         , T1B.Coly
    From table1       as T1A
    inner join table1 as T1B
       on T1B.Col1=T1A.Col1
      and T1B.Colz>T1A.Colz
    where ...

  9. #9
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 997
    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 997
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par Krys9292 Voir le message
    ...
    Juste que je sèche maintenant sur un problème. J'ai une table qui est jointe plusieurs fois à différents champs de ma table principale mais qui prend des valeurs différentes.
    Du coup, quand j'écris les INNER JOIN les uns sur les autres, il ne comprend plus.
    J'imagine qu'il doit se dire, j'ai une relation entre la petite table et la table principale, puis une autre entre cette même petite table et la table principale mais la relation différente... Et il comprend plus, ça le bloque car pour lui c'es incompatible...
    Je ne sais pas, mais avec mes recherches, j'avais juste une idée. Faire deux requêtes séparées et les associer... Je ne sais pas si c'est possible de faire par exemple un SELECT sur deux SELECT
    En fait, la plupart du temps, quand apparait plusieurs fois la même table, ce n'est pas forcément pour avoir les mêmes lignes que la jointure doit se faire. Il faudra dédoubler les version de cette table en ajoutant un alias afin de distinguer les lignes de l'une avec les lignes de l'autre... Un petit exemple

    Soit les tables suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TABLE T_PERSONNE_PRS
    (PRS_ID          INT PRIMARY KEY,
     PRS_NOM         VARCHAR(32),
     PRS_PRENOM      VARCHAR(25),
     PRS_D_NAISSANCE DATE,
     PRS_SEXE        CHAR(5) CHECK(PRS_SEXE IN ('Homme', 'Femme')));
     
    CREATE TABLE T_MARIAGE_MRG
    (MRG_ID           INT PRIMARY KEY,
     MRG_DATE         DATE,
     MRG_LIEU         VARCHAR(128),
     MRG_CONJOINT1    INT REFERENCES T_PERSONNE_PRS (PRS_ID),
     MRG_CONJOINT2    INT REFERENCES T_PERSONNE_PRS (PRS_ID))
    Et les données des personnes comme ci après :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    INSERT INTO T_PERSONNE_PRS VALUES
    (1, 'Martin', 'Martine', '2000-05-15', 'Femme'),
    (2, 'Dupont', 'Philippe', '1999-08-17', 'Homme'),
    (3, 'Schmidt', 'Adolphe', '1940-11-21', 'Homme'),
    (4, 'Lebrun', 'Victoire', '1944-06-06', 'Femme');

    La question simple est : pouvons nous marier une personne avec elle même ?
    Et la réponse évidente est NON !

    Voici un exemple d'insertion dans la table des mariages :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    INSERT INTO T_MARIAGE_MRG VALUES
    (999, '2023-03-15', 'Singapour', 1, 2);
    Il va donc y avoir dans la table de mariage, deux fois des références à une personne, mais ce ne seront jamais les mêmes personnes.
    D’où l’obligation, dans la requête, de faire figurer deux fois la table, avec deux alias différent afin de lire des lignes dissociées !

    Pour retrouver qui s'est marié avec qui voici la solution avec des alias pour toutes les tables :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT MRG_DATE, MRG_LIEU, 
           CONCAT(P1.PRS_PRENOM, ' ', P1.PRS_NOM, ' (', P1.PRS_SEXE, ')') AS CONJOINT1,
           CONCAT(P2.PRS_PRENOM, ' ', P2.PRS_NOM, ' (', P2.PRS_SEXE, ')') AS CONJOINT2
    FROM   T_MARIAGE_MRG AS M
           JOIN T_PERSONNE_PRS AS P1 ON M.MRG_CONJOINT1 = P1.PRS_ID
           JOIN T_PERSONNE_PRS AS P2 ON M.MRG_CONJOINT2 = P2.PRS_ID;
    Et le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    MRG_DATE   MRG_LIEU      CONJOINT1               CONJOINT2
    ---------- ------------- ----------------------- ------------------------
    2023-03-15 Singapour     Martine Martin (Femme)  Philippe Dupont (Homme)
    Le mieux étant re renforcer la table des mariage par une contraintes excluant que l'on se marie avec soi même :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ALTER TABLE T_MARIAGE_MRG ADD CHECK(MRG_CONJOINT1 <> MRG_CONJOINT2);
    Pour information tout ceci était bien précisé dans mon cours, à la même page :
    https://sqlpro.developpez.com/cours/...intures/#LIV-C


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

  10. #10
    Membre confirmé
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Décembre 2022
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Décembre 2022
    Messages : 76
    Par défaut
    Bonjour à tous,

    Avec vos explications, j'ai trouvé une solution qui fonctionne bien :

    je fais des LEFT OUTER JOIN les uns sur les autres en renommant (AS) le résultat (SELECT) à chaque fois pour que les bons champs soient pris en compte.
    Je finis par un simple SELECT en fonction de ce que je veux au final (champs, filtrage, tri).

    Merci à tous.

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

Discussions similaires

  1. Lien entre deux tables dans une BDD tentaculaire
    Par Julian_hdp dans le forum MySQL
    Réponses: 1
    Dernier message: 17/02/2021, 07h46
  2. [Lazarus] Liens entre tables pour afficher une liste
    Par Jon Shannow dans le forum Lazarus
    Réponses: 6
    Dernier message: 23/09/2016, 09h27
  3. Lien entre tables lors d'une requête
    Par thom30 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 10/12/2007, 15h49
  4. Récupérer les relations entre les tables d'une bdd
    Par FRED.G dans le forum Accès aux données
    Réponses: 1
    Dernier message: 16/01/2007, 13h07
  5. Pb de liens entre table pour une requête
    Par syldudu dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 31/08/2006, 17h27

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