Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 09/12/2010, 18h37   #1
Candidat au titre de Membre du Club
 
Inscription : septembre 2003
Messages : 29
Détails du profil
Informations forums :
Inscription : septembre 2003
Messages : 29
Points : 10
Points : 10
Envoyer un message via MSN à sky_perrinos
Par défaut problème de jointure

Bonjour à tous!
J'ai un modèle permettant de manipuler des écoles et des personnes y travaillant:

tbl_ecole (ecole_id, nom)
tbl_site (site_id, ecole_id, site_adresse) // parcequ'une école peut avoir différents sites
tbl_personne (perso_id, perso_nom, perso_prenom, site_id)
tbl_contact(contact_id, perso_id) // table intermédiaire
lnk_contact_fonction(conta_id, fonc_co_id) //table de lien entre contact et fonctions

Objectif: Je dois faire ressortir pour toutes les écoles, le nom des personnes occupant 2 fonctions précises (directeur et secrétaire, id de fonction 26 et 84)
Problème: j'utilise un inner join, donc lorsqu'une école n'a personne pour l'une des 2 fonctions voulues, l'école entière disparaît des résultats au lieu de mettre un simple 'null' dans la fonction concernée.

J'ai essayé de jouer avec les left / right / full inner join, mais ça n'a rien donné (le tout en rappellant deux foix par des alias les trio personne/contact/lnk_contact_fonction):
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT DISTINCT te.ecole_id, 
	ts.site_adresse,
	tp_directeur.perso_nom AS 'directeur',
	tp_secretaire.perso_nom AS 'secrétaire'
 
FROM  TBL_ECOLE te
	INNER JOIN TBL_SITE ts ON ts.ecole_id = te.ecole_id
 
	LEFT OUTER JOIN TBL_PERSONNE tp_directeur ON tp_directeur.site_id = ts.site_id
	LEFT OUTER JOIN TBL_CONTACT tc_directeur ON tc_directeur.perso_id = tp_directeur.perso_id
	LEFT OUTER JOIN LNK_CONTACT_FONCTION lcf_directeur ON lcf_directeur.conta_id = tc_directeur.conta_id
 
	LEFT OUTER JOIN TBL_PERSONNE tp_secretaire ON tp_secretaire.site_id = ts.site_id
	LEFT OUTER JOIN TBL_CONTACT tc_secretaire ON tc_secretaire.perso_id = tp_secretaire.perso_id
	LEFT OUTER JOIN LNK_CONTACT_FONCTION lcf_secretaire ON lcf_secretaire.conta_id = tc_secretaire.conta_id
 
WHERE lcf_directeur.fonct_co_id IN (26)
AND lcf_secretaire.fonct_co_id IN (84)

Quelqu'un sait comment je pourrai faire pour avoir toutes les écoles et un simple 'null' dans la colonne 'secrétaire' quand personne n'est indiqué pour cette fonction?

Merci à tous!
sky_perrinos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 18h49   #2
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
Bonjour,

Pour afficher vos fonction par école le left outer join est la bonne solution.

Concernant la sélection de plusieur fonction, orientez vous vers un "EXISTS" (et un "OR" dans la sous-requete associée sur les 2 fonctions recherchées) afin de ne pas avoir votre problème actuel
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 19h02   #3
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 463
Points : 10 463
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Il faut faire remonter vos filtres dans vos jointures :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT DISTINCT te.ecole_id, 
    ts.site_adresse,
    tp_directeur.perso_nom AS 'directeur',
    tp_secretaire.perso_nom AS 'secrétaire'
 
FROM  TBL_ECOLE te
    INNER JOIN TBL_SITE ts ON ts.ecole_id = te.ecole_id
 
    LEFT OUTER JOIN TBL_PERSONNE tp_directeur ON tp_directeur.site_id = ts.site_id
    LEFT OUTER JOIN TBL_CONTACT tc_directeur ON tc_directeur.perso_id = tp_directeur.perso_id
    LEFT OUTER JOIN LNK_CONTACT_FONCTION lcf_directeur ON lcf_directeur.conta_id = tc_directeur.conta_id AND lcf_directeur.fonct_co_id = 26
 
    LEFT OUTER JOIN TBL_PERSONNE tp_secretaire ON tp_secretaire.site_id = ts.site_id
    LEFT OUTER JOIN TBL_CONTACT tc_secretaire ON tc_secretaire.perso_id = tp_secretaire.perso_id
    LEFT OUTER JOIN LNK_CONTACT_FONCTION lcf_secretaire ON lcf_secretaire.conta_id = tc_secretaire.conta_id AND lcf_secretaire.fonct_co_id = 84
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 10/12/2010, 13h59   #4
Candidat au titre de Membre du Club
 
Inscription : septembre 2003
Messages : 29
Détails du profil
Informations forums :
Inscription : septembre 2003
Messages : 29
Points : 10
Points : 10
Envoyer un message via MSN à sky_perrinos
Bonjour Waldar,

Super ça marche nickel!

Par contre je ne comprends pas pourquoi ça marche.... quelle est la différence entre mettre la restriction sur l'id de fonction dans les jointures plutôt que dans la clause where???

Merci beaucoup en tout cas, au moins ça marche!!
sky_perrinos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/12/2010, 14h34   #5
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 974
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
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 : 10 974
Points : 18 216
Points : 18 216
Envoyer un message via MSN à CinePhil
Si tu mets une condition de restriction sur la table de droite dans une jointure gauche (réciproquement sur la table de gauche dans une jointure droite), c'est comme si tu faisais un INNER JOIN.

Voir ce message pour explication détaillée.

Comme ce problème revient régulièrement, j'en ai profité pour transformer le message cité en article de mon blog.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2010, 23h47   #6
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 950
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 950
Points : 17 764
Points : 17 764
ATTENTION : pas obligatoirement dans la jointure. Cela peut aussi être dans le where mais avec un OR .... IS NULL. Tout dépende de votre besoin !

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/12/2010, 08h53   #7
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 974
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
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 : 10 974
Points : 18 216
Points : 18 216
Envoyer un message via MSN à CinePhil
Exact, j'avais oublié cette possibilité.
Que vaut-il mieux alors ?
1)
Code :
1
2
3
FROM A
LEFT OUTER JOIN B ON A.colA = B.colB
  AND B.col2 = 'une_valeur'
2)
Code :
1
2
3
4
FROM A
LEFT OUTER JOIN B ON A.colA = B.colB
WHERE B.col2 = 'une_valeur'
  OR B.ColB IS NULL
Ça fait une différence du point de vue performances ?
Est-ce que ça donne d'ailleurs le même résultat ?
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/12/2010, 14h50   #8
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 463
Points : 10 463
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Les deux requêtes ne renvoient pas forcément le même résultat, en reprenant les données de votre blog, mais en changeant le booléen de la table B de 0 en null :
Code :
1
2
3
4
5
6
7
8
9
10
11
idA         valA
----------- ----
1           toto
2           titi
3           tata
 
 
idB         idA         valB booleen
----------- ----------- ---- -----------
1           2           riri NULL
2           3           fifi 1
Code :
1
2
3
4
5
6
7
8
9
10
11
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen 
  FROM A 
       LEFT OUTER JOIN B
         ON B.idA     = A.idA 
        AND B.booleen = 1;
 
idA         valA idB         valB booleen
----------- ---- ----------- ---- -----------
1           toto NULL        NULL NULL
2           titi NULL        NULL NULL
3           tata 2           fifi 1
Code :
1
2
3
4
5
6
7
8
9
10
11
12
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen 
  FROM A 
       LEFT OUTER JOIN B
         ON B.idA     = A.idA 
 WHERE B.booleen = 1
    OR B.booleen IS NULL;
 
idA         valA idB         valB booleen
----------- ---- ----------- ---- -----------
1           toto NULL        NULL NULL
2           titi 1           riri NULL
3           tata 2           fifi 1
Donc comme dit SQLPro, ça dépend du besoin !
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/12/2010, 14h54   #9
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 974
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
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 : 10 974
Points : 18 216
Points : 18 216
Envoyer un message via MSN à CinePhil
C'est bien ce qu'il me semblait mais je n'ai pas pris le temps de tester.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« 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 Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/12/2010, 15h34   #10
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 950
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 950
Points : 17 764
Points : 17 764
Le filtre dans le jointure est évalué avant la mise en jointure. Il renvoie donc toutes les lignes de la tables externe, mais pour la table interne, seulement les lignes valuées avec le critère. La cardinalité est celle de la table externe augmenté du produit cartésien de la table interne s'il y a lieu.

Le filtre dans le where exclue les lignes qui ne répondent pas au critère. Certaines lignes de la table externe seront donc rejetées.

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h21.


 
 
 
 
Partenaires

Hébergement Web