Requête sur trois tables

Résolu
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012 - 25 janv. 2012 à 11:08
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 - 15 févr. 2012 à 17:01
Bonjour,

J'ai une table contenant X qui à plusieurs colonnes dont CS_PERS_PRO. Cette table X se rattache à deux autres tables Y et Z.

exemple :

table X :

CS_PERS_PRO (nom colonne)
0125
0354
CTDS
RFBS

-----------------------------
table Y :

CodeCS (nom colonne)
0125
0354

-----------------------------
table Z :

CODE_SERVICE (nom colonne)
CTDS
RFBS


Je souhaite récupérer les libelles des tables Y et Z grace au CS_PERS_PRO en faisant deux jointures mais cela ne marche pas :

SELECT * FROM X WHERE X.CS_PERS_PRO Y.CodeCS AND X.CS_PERS_PRO Z.CODE_SERVICE

Comment puis-je faire ? merci pour vos réponses

19 réponses

cgandco Messages postés 219 Date d'inscription mercredi 26 octobre 2011 Statut Membre Dernière intervention 22 juin 2017 9
25 janv. 2012 à 14:13
Bonjour,

tu dois mettre tes trois tables dans la clause from

comme ceci

SELECT X.*,Y.*,Z.* FROM X,Y,Z WHERE X.CS_PERS_PRO Y.CodeCS AND X.CS_PERS_PRO Z.CODE_SERVICE 


Bonne journée



Faites simple, aussi simple que possible, mais pas simpliste.
A. Einstein.
3
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
25 janv. 2012 à 16:04
bonjour,

la forme "from x, y, z ..." nécessite la présence simultanée de toutes les conditions.
Avec les données que tu montre, le résultat est nul !

il faut faire des "left join" pour obtenir ce que tu veux : lien x->y OU x->z
3
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 janv. 2012 à 10:50
Salut,

perso j'aurais mergé les tables Y & Z pour ensuite faire une jointure normale :

SELECT *
  FROM X,
      (SELECT FY AS FYZ FROM Y UNION ALL SELECT FZ AS FYZ FROM Z) YZ
 WHERE X.FK = YZ.FYZ;


pas sûr que ce soit la méthode la plus rapide,
mais pretty sûr que ça donne ce que tu souhaites ;)

bon SQL
3
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
9 févr. 2012 à 09:43
Si, mais avec left/right join, tu auras 3 colonnes : CS_PERS/CodeCS, CS_PERS_PRO/CodeCS et CS_PERS_PRO/CODE_SERVICE, avec des vides. Pour obtenir 2 colonnes, tu remplaces les 2 dernières par un lien vers l'union de 2 tables.
Le tout en une seule requête. C'est la requête imbriquée qui pose un problème ?
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
9 févr. 2012 à 11:56
Comme quoi j'écris pas que des âneries
3
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
9 févr. 2012 à 15:39
Si j'ai bien compris ce que tu cherches, il ne faut pas mettre le "where..." ni la référence à ENTITES telle que tu l'as mise, mais quelque chose comme
FROM (PERSONNE P LEFT JOIN (..) ENTITEPRO ON CS_PERS_PRO=CentrePro)
Left Join ENTITES E On P.CS_PERS=E.CodeCS
3
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
15 févr. 2012 à 17:01
Pas de where pour le lien, sinon tu exiges la présence des 2 extrêmités, et ce n'est pas ce que tu veux.

From PERSONNE P left join HISTOCARRIERE H on P.MATRI_PERSONNE = H.Matricule

le reste doit aller
3
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
7 févr. 2012 à 11:40
Bon j'ai décidé de mettre en ligne mon problème :



On peut retrouver le libelle du centre de secours d'une personne grâce à son code (CS_PERS pour les pompiers volontaire et CS_PERS_PRO pour les pompiers professionnel).

CS_PERS_PRO de la table PERSONNE peut etre soit un code de la table ENTITES soit un code de la table SERVICE_SEDIT.

Il me faut une requete qui me permet de prendre les matricules, noms, prénoms, les libellés des grades des volontaires et des professionnels (LIBELLE_GRADE des tables GRADE et GRADE_SEDIT), les libellé des centres de secours des volontaires et professionnels (LIBELLECS et LIBELLE_SERVICE des tables ENTITES et SERVICE_SEDIT) des peronnes ayant le statut de volontaire et professionnel à la fois (CS_PERS<>'' AND CS_PERS_PRO<>'').

Requête à revoir :

SELECT P.MATRI_PERSSONNE, E.LIBELLECS, S.LIBELLE_SERVICE, G.LIBELLE_GRADE as LBL_G_V , GS.LIBELLE_GRADE as LBL_G_P
FROM PERSONNE LEFT JOIN ENTITES ON PERSONNE.CS_PERS_PRO=E.CodeCS, PERSONNE LEFT JOIN SERVICE_SEDIT ON PERSONNE.CS_PERS_PRO=S.CODE_SERVICE, ENTITES E, SERVICE_SEDIT S, GRADE G, GRADE_SEDIT GS
WHERE P.CS_PERS=E.CS_PERS AND GS.CODE_GRADE=P.GRADE_PRO AND G.CODE_GRADE=P.GRADE_OBTENT AND NOT CS_PERS='' AND NOT CS_PERS_PRO='' AND P.CS_PERS=E.CodeCS;

--> je ne peux pas me repérer par rapport au CODE_STATUT pour sélectionner les pro et les volontaires car par défaut le statut (CODE_STATUT='VOL') est affecté à une personne volontaire ou volontaire et pro. Le statut (CODE_STATUT='PRO') ne donne que les professionnels.
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
7 févr. 2012 à 12:39
bonjour,

je vois que tu n'es pas prêt d'être au bout !

revoie la doc de ton sgbd sur le sql (qu'as-tu comme sgbd ?), en particulier les "join", "left" et right".

rapidement, tu fais :
- soit from t1, t2 where t1.x = t2.x : tu n'obtiens que les enregistrements liés
- soit from t1 left join t2 on t1.x = t2.x : tout t1 + les t2 liés

toi, tu as écrit un mix : from t1 left join t2 on t1.x, t2 where t1.x = t2.x
rien gagné, pas de résultat !
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
7 févr. 2012 à 13:43
Je travail sur une base existante hyperfile par le biais d'excel (odbc).
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
7 févr. 2012 à 15:04
Je bloque au niveau des jointures sur les 3 tables (PERSONNE, ENTITES, SERVICE_SEDIT).

J'ai fais une requête (qui ne convient pas) la plus clair possible :

SELECT E.LibelleCS as lbl, S.LIBELLE_SERVICE as lbl_pro
FROM PERSONNE P LEFT JOIN ENTITES E ON P.CS_PERS_PRO=E.CodeCS LEFT JOIN SERVICE_SEDIT S ON P.CS_PERS_PRO=S.CODE_SERVICE
WHERE P.CS_PERS=E.CODECS ;

C'est simple :
-1 table PERSONNE (table parente) avec deux colonnes (CS_PERS, CS_PERS_PRO)

-1 table ENTITES qui contient le libellé(LibelleCS) de CS_PERS et 'une fois sur deux' le libellé(LibelleCS) de CS_PERS_PRO

-1 table SERVICE_SEDIT qui contient le reste des libellés(LIBELLE_SERVICE) de CS_PERS_PRO

--------------------------------------------
info pour les relations (noms de colonnes) :

CS_PERS = CodeCS
CS_PERS_PRO = CodeCS ou CODE_SERVICE

--------------------------------------------
Je dois avoir comme résultat 2 colonnes :

lbl et lbl_pro
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
7 févr. 2012 à 17:58
Alors la solution de jopop est très bien.
As-tu essayé ?
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
7 févr. 2012 à 18:38
Il n'y a pas moyen de la faire en 1 requete ?
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
9 févr. 2012 à 10:25
Je n'ai jamais fait de requêtes imbriquées dans la clause 'FROM', seulement dans la 'WHERE'. (cf méthode de jopop)
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
9 févr. 2012 à 10:57
Géniale, je crois que c'est ça :

SELECT MATRI_PERSONNE, LBLPRO FROM PERSONNE, (SELECT LibelleCS as LBLPRO, CodeCS AS CentrePro FROM ENTITES UNION ALL SELECT LIBELLE_SERVICE as LBLPRO, CODE_SERVICE AS CentrePro FROM SERVICE_SEDIT) ENTITEPRO WHERE PERSONNE.CS_PERS_PRO = ENTITEPRO.CentrePro
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
9 févr. 2012 à 12:18
Plus dur maintenant, disons que dans CS_PERS il y a quelque chose et que dans CS_PERS_PRO il n'y a rien, comment je peux faire pour que ca me sélectionne quand même le champs vide ?
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
9 févr. 2012 à 12:54
comment je peux faire ma jointure externe ?
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
9 févr. 2012 à 13:17
Ceci me donne le même résultat :/ :

SELECT P.MATRI_PERSONNE, P.NOM_PERS, P.PRENOM_PERS, LBLPRO, E.LibelleCS FROM ENTITES E, PERSONNE P LEFT JOIN (SELECT LibelleCS as LBLPRO, CodeCS AS CentrePro FROM ENTITES UNION ALL SELECT LIBELLE_SERVICE as LBLPRO, CODE_SERVICE AS CentrePro FROM SERVICE_SEDIT) ENTITEPRO ON CS_PERS_PRO=CentrePro WHERE P.CS_PERS=E.CodeCS
0
cartman29 Messages postés 60 Date d'inscription dimanche 7 novembre 2010 Statut Membre Dernière intervention 4 août 2012
15 févr. 2012 à 09:28
Merci déjà pour tout ce que vous avez fait (tpoinsot, jopop,... :) ). J'ai une dernière question à laquelle j'ai passé toute ma journée d'hier sans y trouver de réponses :

J'ai ma table
PERSONNE(colonne MATRI_PERSONNE,...)
et une table
HISTOCARRIERE(colonne Matricule, DATE_GRADE)

Je cherche à prendre toutes les MAX(DATE_GRADE) de chaque matricules (matricule unique avec la date maximum de celui-ci) et si il manque un matricule il faut quand même que ça ajoute la le matricule.

J'arrive à faire cette requête sauf avec la dernière condition :

"SELECT P.DATE_NAISS, MAX(H.DATE_GRADE) as dtgrade, P.MATRI_PERSONNE, P.ADR_PERS, P.CP_PERS, G.LIBELLE_GRADE as Grade, P.VILLE_PERS, P.NOM_PERS, P.PRENOM_PERS, E.LibelleCS FROM HISTOCARRIERE H, GRADE G, ENTITES E, PERSONNE P WHERE P.CS_PERS=E.CodeCS AND CS_PERS_PRO='' AND P.GRADE_OBTENT=G.CODE_GRADE AND P.MATRI_PERSONNE=H.Matricule AND " & chaine & " GROUP BY P.DATE_NAISS, P.MATRI_PERSONNE, G.LIBELLE_GRADE, P.ADR_PERS, P.CP_PERS, P.VILLE_PERS, P.NOM_PERS, P.PRENOM_PERS, E.LibelleCS;"

Je pense qu'il faut faire quelque chose comme :

WHERE DATE_GRADE=(SELECT MAX(DATE_GRADE) AS dte FROM HISTOCARRIERE) avec une jointure gauche mais je n'y arrive pas :/
0
Rejoignez-nous