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 :

Requête complexe avec 14 tables


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2010
    Messages
    175
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 175
    Par défaut Requête complexe avec 14 tables
    Bonjour,

    je travaille sur une base de données constituée de 25 tables environ.
    Le fonctionnement est "simple". Les tables représentent des informations concernant les salariés de la société, c'est-à-dire que j'ai une table contenant les informations personnelles de du salarié, une table contenant son salaire, une table contenant son poste, ...
    Pourquoi prendre des tables pour chaque information? La raison est simple. La société fonctionne par période est donc ce sont les informations concernant une période précise (et donc j'ai une table contenant les période)

    Je cherche à faire une requête me permettant de récupérer les informations de tous les salariés. Je suis arrivé à cette requête
    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
    SELECT Employe.Matricule, Employe.Soc, Employe.Nom, Employe.Prenom, Employe.Sexe, Employe.Panel, Employe.Actif, ListeSocietes.Libelle AS LibelleSociete, Etablissement.Ets, Section.Code AS CodeSection, ListeSections.Libelle AS LibelleSection, Classification.Code AS CodeClassification, ListeClassifications.Libelle AS LibelleClassification, ListeClassifications.Niveau, Statut.Libelle AS LibelleStatut, Pole_Technologique.Valeur AS PoleTechno, Site.Libelle AS LibelleSite, Contrat.Libelle AS LibelleContrat, ListeResponsables.Nom + ' ' + ListeResponsables.Prenom AS NomResponsable, Activite.Pourcentage AS TauxActivite
    FROM Employe
    INNER JOIN ListeSocietes ON Employe.Soc = ListeSocietes.Soc
    INNER JOIN Etablissement ON Employe.Matricule = Etablissement.Matricule AND Employe.Soc = Etablissement.Soc
    INNER JOIN Section ON Employe.Matricule = Section.Matricule AND Employe.Soc = Section.Soc
    INNER JOIN ListeSections ON ListeSocietes.Soc = ListeSections.Soc AND Section.Soc = ListeSections.Soc AND Section.Code = ListeSections.Code
    INNER JOIN Classification ON Employe.Matricule = Classification.Matricule AND Employe.Soc = Classification.Soc
    INNER JOIN ListeClassifications ON ListeSocietes.Soc = ListeClassifications.Soc AND Classification.Soc = ListeClassifications.Soc AND Classification.Code = ListeClassifications.Code
    INNER JOIN Statut ON Employe.Matricule = Statut.Matricule AND Employe.Soc = Statut.Soc
    INNER JOIN Pole_Technologique ON Employe.Matricule = Pole_Technologique.Matricule AND Employe.Soc = Pole_Technologique.Soc
    INNER JOIN Site ON Employe.Matricule = Site.Matricule AND Employe.Soc = Site.Soc
    INNER JOIN Contrat ON Employe.Matricule = Contrat.Matricule AND Employe.Soc = Contrat.Soc
    INNER JOIN Responsable ON Employe.Matricule = Responsable.Matricule AND Employe.Soc = Responsable.Soc
    INNER JOIN ListeResponsables ON ListeSocietes.Soc = ListeResponsables.Soc AND Responsable.Soc = ListeResponsables.Soc AND Responsable.idResponsable = ListeResponsables.id
    INNER JOIN Activite ON Employe.Matricule = Activite.Matricule AND Employe.Soc = Activite.Soc
    WHERE (Etablissement.DatePeriode = '01/01/2010') AND (Section.DatePeriode = '01/01/2010') AND (Classification.DatePeriode = '01/01/2010') AND (Statut.DatePeriode = '01/01/2010') AND (Pole_Technologique.DatePeriode = '01/01/2010') AND (Site.DatePeriode = '01/01/2010') AND (Contrat.DatePeriode = '01/01/2010') AND (Responsable.DatePeriode = '01/01/2010') AND (Activite.DatePeriode = '01/01/2010')

    Cette requête me permet bel et bien de récupérer les informations concernant les salariés et la période voulut MAIS... les salariés ne possédant pas d'information pour cette période sont mis à l'écart... J'aimerai lister TOUS les salariés, et dans le cas où il n'y aurait pas d'information récupérer des valeurs NULL ou quelquechose du genre
    Je ne maîtrise malheureusement pas assez les requêtes SQL pour corriger mon problème. Est ce que quelqu'un voit où est ce que mon problème réside?

  2. #2
    Membre émérite Avatar de Oishiiii
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2009
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Août 2009
    Messages : 508
    Par défaut
    Bonjour,

    Pour faire cela il faut utiliser des jointures externes (LEFT [OUTER] JOIN).
    Voyez le cours sur les jointures pour plus de détails.

  3. #3
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2010
    Messages
    175
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 175
    Par défaut
    Merci pour la réponse aussi rapide.
    J'avais déjà lu ce cours mais je ne voyais pas comment l'adapter.
    J'ai réussi à obtenir la requête me donnant le bon résultat.

    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
    SELECT Employe.Matricule, Employe.Soc, Employe.Nom, Employe.Prenom, Employe.Sexe, Employe.Panel, Employe.Actif," _
                            & "ListeSocietes.Libelle AS LibelleSociete, Etablissement.Ets," _
                            & "Section.Code AS CodeSection, ListeSections.Libelle AS LibelleSection," _
                            & "Classification.Code AS CodeClassification, ListeClassifications.Libelle AS LibelleClassification, ListeClassifications.Niveau, Statut.Libelle AS LibelleStatut," _
                            & "Pole_Technologique.Valeur AS PoleTechno," _
                            & "Site.Libelle AS LibelleSite," _
                            & "Contrat.Libelle AS LibelleContrat," _
                            & "ListeResponsables.Nom + ' ' + ListeResponsables.Prenom AS NomResponsable," _
                            & "Activite.Pourcentage AS TauxActivite" _
                            & " FROM Employe" _
                            & " LEFT OUTER JOIN ListeSocietes ON Employe.Soc = ListeSocietes.Soc" _
                            & " LEFT OUTER JOIN Etablissement ON Employe.Matricule = Etablissement.Matricule AND Employe.Soc = Etablissement.Soc" _
                            & " LEFT OUTER JOIN Section ON Employe.Matricule = Section.Matricule AND Employe.Soc = Section.Soc" _
                            & " LEFT OUTER JOIN ListeSections ON ListeSocietes.Soc = ListeSections.Soc AND Section.Soc = ListeSections.Soc AND Section.Code = ListeSections.Code" _
                            & " LEFT OUTER JOIN Classification ON Employe.Matricule = Classification.Matricule AND Employe.Soc = Classification.Soc" _
                            & " LEFT OUTER JOIN ListeClassifications ON ListeSocietes.Soc = ListeClassifications.Soc AND Classification.Soc = ListeClassifications.Soc AND Classification.Code = ListeClassifications.Code" _
                            & " LEFT OUTER JOIN Statut ON Employe.Matricule = Statut.Matricule AND Employe.Soc = Statut.Soc" _
                            & " LEFT OUTER JOIN Pole_Technologique ON Employe.Matricule = Pole_Technologique.Matricule AND Employe.Soc = Pole_Technologique.Soc" _
                            & " LEFT OUTER JOIN Site ON Employe.Matricule = Site.Matricule AND Employe.Soc = Site.Soc" _
                            & " LEFT OUTER JOIN Contrat ON Employe.Matricule = Contrat.Matricule AND Employe.Soc = Contrat.Soc" _
                            & " LEFT OUTER JOIN Responsable ON Employe.Matricule = Responsable.Matricule AND Employe.Soc = Responsable.Soc" _
                            & " LEFT OUTER JOIN ListeResponsables ON ListeSocietes.Soc = ListeResponsables.Soc AND Responsable.Soc = ListeResponsables.Soc AND Responsable.idResponsable = ListeResponsables.id" _
                            & " LEFT OUTER JOIN Activite ON Employe.Matricule = Activite.Matricule AND Employe.Soc = Activite.Soc" _
                            & " WHERE ((Etablissement.DatePeriode = '01/01/2010') AND (Section.DatePeriode = '01/01/2010') AND (Classification.DatePeriode = '01/01/2010') AND (Statut.DatePeriode = '01/01/2010') AND (Pole_Technologique.DatePeriode = '01/01/2010') AND (Site.DatePeriode = '01/01/2010') AND (Contrat.DatePeriode = '01/01/2010') AND (Responsable.DatePeriode = '01/01/2010') AND (Activite.DatePeriode = '01/01/2010'))" _
                            & " OR ListeSocietes.Libelle IS NULL OR Etablissement.Ets IS NULL OR Section.code IS NULL OR ListeSections.Libelle IS NULL OR Classification.Code IS NULL OR ListeClassifications.Libelle IS NULL OR ListeClassifications.Niveau IS NULL OR Statut.Libelle IS NULL OR Pole_Technologique.Valeur IS NULL OR Site.Libelle IS NULL OR Contrat.Libelle IS NULL OR ListeResponsables.Nom + ' ' + ListeResponsables.Prenom IS NULL OR Activite.Pourcentage IS NULL"

    J'ai tout de même une question.
    A un moment il est dit que
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT CLI_NOM, TEL_NUMERO
    FROM   T_CLIENT C 
           LEFT OUTER JOIN T_TELEPHONE T
                ON C.CLI_ID = T.CLI_ID
    WHERE  TYP_CODE = 'FAX' OR TYP_CODE IS NULL
    revient au même que
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT CLI_NOM, TEL_NUMERO
    FROM   T_CLIENT C 
           LEFT OUTER JOIN T_TELEPHONE T
                ON C.CLI_ID = T.CLI_ID AND TYP_CODE IS NULL

    J'aimerais bien adapter ma longue ligne de OR de la même façon que le deuxième exemple mais je ne comprends pas vraiment les critères à mettre.
    Si quelqu'un a un peu de temps je suis preneur...

    Merci d'avance

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Par défaut
    Bonjour,

    Je ne trouve pas ces deux requêtes équivalentes.
    SQLPro filtre le résultat de la première requête sur des colonnes qui ne font pas partie du SELECT.

    La première requête lui retourne les clients qui ont un n° de fax et ceux qui ont un numéro de téléphone dont on ne connaît pas le type (ce peut être le bureau, le domicile, ... : on ne le sait pas)
    La seconde requête retourne tous les clients, que l'on connaisse le type de leur numéro de téléphone ou non.
    En revanche elle ne retourne pas le téléphone de ceux dont le type de téléphone n'est pas FAX.
    Ce n'est donc pas la même chose qui est exprimée, mais cela répond à la question :
    Que faut-il modifier dans la requête pour obtenir une ligne "BOUVIER" avec aucune référence de téléphone associée dans la réponse ?
    Dans la première requête SQLPro filtre le résultat, alors que dans la seconde, il filtre la jointure.
    La différence est subtile mais elle existe
    Avec les OR, vous allez obtenir toutes les lignes qui ne vérifient pas la demi-jointure ... je ne crois pas que ce soit ce que vous cherchiez, et vous pouvez donc tout simplement les enlever.

    Autres remarques :

    - vous pouvez faire de votre requête, qui est assez longue, une procédure stockée,
    - vous n'avez pas qualifié le nom des objets qui participent à votre requête par le nom du schéma auquel ils appartiennent, ce qui oblige SQL Server à le rechercher dans les tables de métadonnées
    - Utilisez le format de dates ISO, cela vous évitera des ennuis (YYYYMMDD)
    - aérez votre code :

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    SELECT		Employe.Matricule
    		, Employe.Soc
    		, Employe.Nom
    		, Employe.Prenom
    		, Employe.Sexe
    		, Employe.Panel
    		, Employe.Actif,
    		, ListeSocietes.Libelle AS LibelleSociete
    		, Etablissement.Ets
    		, Section.Code AS CodeSection
    		, ListeSections.Libelle AS LibelleSection,
    		, Classification.Code AS CodeClassification
    		, ListeClassifications.Libelle AS LibelleClassification
    		, ListeClassifications.Niveau
    		, Statut.Libelle AS LibelleStatut,
    		, Pole_Technologique.Valeur AS PoleTechno,
    		, Site.Libelle AS LibelleSite,
    		, Contrat.Libelle AS LibelleContrat,
    		, ListeResponsables.Nom + ' ' + ListeResponsables.Prenom AS NomResponsable,
    		, Activite.Pourcentage AS TauxActivite
    FROM		dbo.Employe
    LEFT JOIN	dbo.ListeSocietes
    			ON Employe.Soc = ListeSocietes.Soc
    LEFT JOIN	dbo.Etablissement
    			ON Employe.Matricule = Etablissement.Matricule
    			AND Employe.Soc = Etablissement.Soc
    LEFT JOIN	dbo.Section
    			ON Employe.Matricule = Section.Matricule
    			AND Employe.Soc = Section.Soc
    LEFT JOIN	dbo.ListeSections
    			ON ListeSocietes.Soc = ListeSections.Soc
    			AND Section.Soc = ListeSections.Soc
    			AND Section.Code = ListeSections.Code
    LEFT JOIN	dbo.Classification
    			ON Employe.Matricule = Classification.Matricule
    			AND Employe.Soc = Classification.Soc
    LEFT JOIN	dbo.ListeClassifications
    			ON ListeSocietes.Soc = ListeClassifications.Soc
    			AND Classification.Soc = ListeClassifications.Soc
    			AND Classification.Code = ListeClassifications.Code
    LEFT JOIN	dbo.Statut
    			ON Employe.Matricule = Statut.Matricule
    			AND Employe.Soc = Statut.Soc
    LEFT JOIN	dbo.Pole_Technologique
    			ON Employe.Matricule = Pole_Technologique.Matricule
    			AND Employe.Soc = Pole_Technologique.Soc
    LEFT JOIN	dbo.Site
    			ON Employe.Matricule = Site.Matricule
    			AND Employe.Soc = Site.Soc
    LEFT JOIN	dbo.Contrat
    			ON Employe.Matricule = Contrat.Matricule
    			AND Employe.Soc = Contrat.Soc
    LEFT JOIN	dbo.Responsable
    			ON Employe.Matricule = Responsable.Matricule
    			AND Employe.Soc = Responsable.Soc
    LEFT JOIN	dbo.ListeResponsables
    			ON ListeSocietes.Soc = ListeResponsables.Soc
    			AND Responsable.Soc = ListeResponsables.Soc
    			AND Responsable.idResponsable = ListeResponsables.id
    LEFT JOIN	dbo.Activite
    			ON Employe.Matricule = Activite.Matricule
    			AND Employe.Soc = Activite.Soc
    WHERE
    (
    	Etablissement.DatePeriode = '20100101'
    	AND Section.DatePeriode = '20100101'
    	AND Classification.DatePeriode = '20100101'
    	AND Statut.DatePeriode = '20100101'
    	AND Pole_Technologique.DatePeriode = '20100101'
    	AND Site.DatePeriode = '20100101'
    	AND Contrat.DatePeriode = '20100101'
    	AND Responsable.DatePeriode = '20100101'
    	AND Activite.DatePeriode = '20100101'
    )
    @++

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Je pense qu'il y a une erreur dans la seconde requête, qui devrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT C.CLI_NOM, T.TEL_NUMERO
      FROM T_CLIENT as C 
           LEFT OUTER JOIN T_TELEPHONE as T
           ON C.CLI_ID   = T.CLI_ID
          AND T.TYP_CODE = 'FAX'

  6. #6
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2010
    Messages
    175
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2010
    Messages : 175
    Par défaut
    Citation Envoyé par elsuket Voir le message
    Bonjour,

    Je ne trouve pas ces deux requêtes équivalentes.
    SQLPro filtre le résultat de la première requête sur des colonnes qui ne font pas partie du SELECT.

    La première requête lui retourne les clients qui ont un n° de fax et ceux qui ont un numéro de téléphone dont on ne connaît pas le type (ce peut être le bureau, le domicile, ... : on ne le sait pas)
    La seconde requête retourne tous les clients, que l'on connaisse le type de leur numéro de téléphone ou non.
    En revanche elle ne retourne pas le téléphone de ceux dont le type de téléphone n'est pas FAX.
    Je me suis peut être mal exprimé quand je parlais d'équivalence des requêtes. Il va de soit qu'il manque la partie "filtrant" les numéros de téléphone de type FAX

    Citation Envoyé par elsuket Voir le message
    Ce n'est donc pas la même chose qui est exprimée, mais cela répond à la question :


    Dans la première requête SQLPro filtre le résultat, alors que dans la seconde, il filtre la jointure.
    La différence est subtile mais elle existe
    Avec les OR, vous allez obtenir toutes les lignes qui ne vérifient pas la demi-jointure ... je ne crois pas que ce soit ce que vous cherchiez, et vous pouvez donc tout simplement les enlever.
    Je cherche justement à obtenir la liste de tous les salariés, qu'ils aient des informations complémentaires ou non

    Citation Envoyé par elsuket Voir le message
    Autres remarques :

    - vous pouvez faire de votre requête, qui est assez longue, une procédure stockée,
    C'est déjà le cas

    Citation Envoyé par elsuket Voir le message
    - vous n'avez pas qualifié le nom des objets qui participent à votre requête par le nom du schéma auquel ils appartiennent, ce qui oblige SQL Server à le rechercher dans les tables de métadonnées
    Qu'entendez vous par "le nom du schéma auquel ils appartiennent?

    Citation Envoyé par elsuket Voir le message
    - Utilisez le format de dates ISO, cela vous évitera des ennuis (YYYYMMDD)
    La date a été prise pour un exemple, en principe c'est une procédure stockée, et c'est donc un paramètre de ma procédure

    Citation Envoyé par elsuket Voir le message
    @++
    Merci pour toutes les explications


    Citation Envoyé par Waldar Voir le message
    Je pense qu'il y a une erreur dans la seconde requête, qui devrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT C.CLI_NOM, T.TEL_NUMERO
      FROM T_CLIENT as C 
           LEFT OUTER JOIN T_TELEPHONE as T
           ON C.CLI_ID   = T.CLI_ID
          AND T.TYP_CODE = 'FAX'
    J'avais copier/coller la requête directement du cours sur les jointures mais il est vrai que pour la correspondance exacte des deux requêtes, il faudrait modifier la seconde comme vous l'avez fait

Discussions similaires

  1. Requête complexe avec plusieurs lignes par table
    Par Iwazaru dans le forum Requêtes
    Réponses: 5
    Dernier message: 01/09/2009, 09h46
  2. Requête : Insert avec plusieurs tables
    Par bleu_ciel dans le forum Access
    Réponses: 4
    Dernier message: 01/06/2006, 21h42
  3. [SQL] Requête complexe avec appel multiple à la même table
    Par Julien Dufour dans le forum Langage SQL
    Réponses: 9
    Dernier message: 14/04/2005, 14h12
  4. Encore une requête complexe sur plusieurs tables
    Par DenPro dans le forum Langage SQL
    Réponses: 5
    Dernier message: 09/12/2003, 19h05
  5. Requête complexe sur plusieurs table
    Par DenPro dans le forum Langage SQL
    Réponses: 13
    Dernier message: 25/11/2003, 17h50

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