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

MS SQL Server Discussion :

Problème de visibilité de table/colonne dans une requête


Sujet :

MS SQL Server

  1. #1
    Membre actif Avatar de MicaelFelix
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2006
    Messages
    254
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2006
    Messages : 254
    Points : 221
    Points
    221
    Par défaut Problème de visibilité de table/colonne dans une requête
    Bonjour,

    Je vous explique mon problème, souvent lorsque je fais une requête et qu'elle est simple, je ne descend pas dans les niveaux inférieurs en utilisant des selects imbriqués, mais lorsque je n'ai pas le choix, je me retrouve souvent "bloqué" avec "...column prefix '...' does not match with a table name or alias..."

    Je suppose que c'est un problème de compréhension du SQL car si on ne peut pas faire autrement, le sql ne serait pas très pratique comme langage...

    Je vous montre un exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ...
    	INNER JOIN (SELECT Client_ID,Sexe,Nom,Prenom FROM tClient)tClient ON tClient.Client_ID = tDossier.Client_ID 
    	LEFT JOIN tClient_Adresse ON tClient.Client_ID = tClient_Adresse.Client_ID
    	,(SELECT TOP 1 * FROM
    	(SELECT Adresse_ID FROM dbo.tClient_Adresse WHERE dbo.tClient_Adresse.Client_ID=tClient.Client_ID) tC_A 
    INNER JOIN tAdresse ON tAdresse.Adresse_ID = tC_A.Adresse_ID2
    	ORDER BY tAdresse.Principal)t2
    J'ai simplifié le code pour une meilleure compréhension du problème.
    Ici en fait j'ai un client, une ou plusieurs adresses pour le client (ce qui explique la table de liaison tClient_Adresse), et je veux récupérer une seule de ces adresses, celle qui est définie en tant que principale.
    Mon problème est que tClient.Client_ID n'est pas visible à l'intérieur des selects imbriqués... bref j'ai l'impression que dès qu'on "descend" d'un niveau on n'a plus accès aux autres tables, c'est peut être normal mais alors comment fais ton pour reprendre des valeurs des colonnes qui sont plus "hautes" (comme Client_ID de la tClient_ID par exemple) ?

    J'ai l'impression que je n'ai pas compris des choses parce que ce genre de problème me revient souvent... alors ce que je fais la plupart du temps c'est que j'essaye d'éviter ce genre de cas complexe, en faisant (quand c'est possible, quand il n'y a qu'une valeur à récupérer sur un enregistrement d'un fichier) des appels du genre dbo.mafonction(Client_ID) qui me retournerait l'adresse (numéro civique)... mais ce genre de principe est mauvais car dès que je veux plus d'une "case" (par exemple le numéro civique + le code postal + la ville), c'est pas possible avec les appels de fonctions qui ne renvoient basiquement qu'une valeur...

    J'espère que vous comprenez mon problème, je vous remercie à l'avance de l'aide que vous pourrez me donner.

    Merci.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 056
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 056
    Points : 1 216
    Points
    1 216
    Par défaut
    est-ce que tu peux poster le code complet de ta requête ? C'est souvent plus simple que d'avoir un extrait du code qui n'est pas forcément représentatif du pb.

    Mais si ta table t_Client n'est pas dans ta clause FROM (pas dans un FROM d'un sous-select, dans le FROM principal), tu n'as pas bcp de chances d'arriver à tes fins.
    Emmanuel T.

  3. #3
    Membre actif Avatar de MicaelFelix
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2006
    Messages
    254
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2006
    Messages : 254
    Points : 221
    Points
    221
    Par défaut
    C'est visible dans le code que j'avais mis (cf première ligne, en dessous des ...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INNER JOIN (SELECT Client_ID,Sexe,Nom,Prenom FROM tClient)tClient
    et c'est bien entendu dans le FROM principal, j'ai juste enlevé ce qui est dessus pour faciliter la compréhension.
    L'appel à tClient.Client_ID pose problème alors que tClient est bien dans le from principal (au dessus), ça se voit bien dans le code qui est donné, pourtant j'ai l'impression que quand on descend un niveau il perd la visibilité de tclient.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2006
    Messages
    730
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 730
    Points : 923
    Points
    923
    Par défaut
    INNER JOIN (SELECT Client_ID,Sexe,Nom,Prenom FROM tClient)tClient
    çà sert a quoi ?

    un aurai suffit d'autant plus que tu caste le nom de la table par son propre nom

    au final ta requête peut être simplifiée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT TOP 1 * FROM
    tClient ON tClient.Client_ID = tDossier.Client_ID 
    LEFT JOIN tClient_Adresse ON tClient.Client_ID = tClient_Adresse.Client_ID
    LEFT JOIN tAdresse ON tAdresse.Adresse_ID = tClient_Adresse.Adresse_ID
    ORDER BY tAdresse.Principal
    Errare humanum est, perseverare diabolicum (Sénèque)

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 056
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 056
    Points : 1 216
    Points
    1 216
    Par défaut
    et c'est bien entendu dans le FROM principal
    excuse-moi je ne suis pas devin
    Emmanuel T.

  6. #6
    Membre actif Avatar de MicaelFelix
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2006
    Messages
    254
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2006
    Messages : 254
    Points : 221
    Points
    221
    Par défaut
    Citation Envoyé par kagemaru
    excuse-moi je ne suis pas devin
    C'était pas à prendre méchamment, désolé si tu l'as mal pris, c'était juste pour dire que oui c'est dans le from principal.

    aurai suffit d'autant plus que tu caste le nom de la table par son propre nom
    Moins tu prends de champs dans la table, moins sa représentation sera "lourde" dans la mémoire du serveur pour les calculs des requêtes, plus la requête sera performante, enfin c'est ce qu'on m'a appris, peut être que j'ai tort dans le cas d'un inner join (bien que ça m'étonnerai).
    C'est juste pour une question de performance.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT TOP 1 * FROM
    tClient ON tClient.Client_ID = tDossier.Client_ID 
    LEFT JOIN tClient_Adresse ON tClient.Client_ID = tClient_Adresse.Client_ID
    LEFT JOIN tAdresse ON tAdresse.Adresse_ID = tClient_Adresse.Adresse_ID
    ORDER BY tAdresse.Principal
    Dans mon cas c'est pas ce que je veux car la requête est plus complexe que ça en vrai (je ne veux pas retourner que l'adresse).

    Je pense faire comme ça au final :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    tClient ON tClient.Client_ID = tDossier.Client_ID 
    LEFT JOIN (SELECT TOP 1 * FROM tClient_Adresse INNER JOIN tAdresse ON tAdresse.Adresse_ID = tClient_Adresse.Adresse_ID ORDER BY tAdresse.Principal) tC_A ON tClient.Client_ID = tC_A.Client_ID
    Mais à votre avis, est-ce qu'il produit la requête avant d'appliquer le ON tClient.Client_ID = tC_A.Client_ID ? Bref est-ce qu'il va faire l'inner join puis ensuite considérer la condition dans ON ... ?
    C'est toujours une histoire d'optimisation, parce que c'est une base de données de milliers de clients donc je dois faire au mieux pour que ça soit le moins gourmand en ressources.

    Merci d'avance.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 056
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 056
    Points : 1 216
    Points
    1 216
    Par défaut
    que raconte le plan d'exécution ? ça te permettra de voir dans quel ordre il traite les opérations et le coût en ressource de chaque exécution.
    (Ctrl+K dans l'analyseur de requêtes)
    Emmanuel T.

  8. #8
    Membre actif Avatar de MicaelFelix
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2006
    Messages
    254
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2006
    Messages : 254
    Points : 221
    Points
    221
    Par défaut
    Bon j'arrive toujours pas à ce que je veux alors je vais vous montrer tout ça sera plus simple :
    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
    SELECT TOP 100 tClient.Sexe,tClient.Nom,tClient.Prenom,Activite,Referent_Nom,tDossier.Dt_Debut,tDossier.Dt_Fin,
    (SELECT TOP 1 Prenom + ' ' + Nom FROM 
    	(SELECT Assistance_ID,Usager_ID,Dossier_ID FROM tDossier_Assistance )tD_A 
    	INNER JOIN (SELECT TOP 1 Assistance_ID FROM tAssistance WHERE Afficher_Sur_Rapport=1)tA ON tD_A.Assistance_ID=tA.Assistance_ID AND tD_A.Dossier_ID=tDossier.Dossier_ID
    	INNER JOIN tUsager ON tUsager.Usager_ID=tD_A.Usager_ID
    ) 
    As Usager_Nom,tClient_Adresse.Adresse_ID,
    Adresse_Civique,Ville,tMunicipalite.Nom As Municipalite_Nom,Cd_Postal,Etat,Pays
    	FROM (SELECT * FROM tDossier )tDossier 
    	INNER JOIN (SELECT Client_ID,Sexe,Nom,Prenom FROM tClient)tClient ON tClient.Client_ID = tDossier.Client_ID 
    	INNER JOIN (SELECT Nom As Activite, Activite_ID FROM tActivite )tA ON tA.Activite_ID = tDossier.Activite_ID 
    	INNER JOIN (SELECT Referent_ID,Nom As Referent_Nom FROM tReferent )tR ON tR.Referent_ID = tDossier.Referent_ID
    	LEFT JOIN tClient_Adresse ON tClient.Client_ID = tClient_Adresse.Client_ID
    	LEFT JOIN (SELECT TOP 1 Adresse_ID,Adresse_Civique,tAdresse.Ville,Municipalite_ID,Cd_Postal,Etat,Pays FROM tAdresse ORDER BY Principal DESC)vAdresse ON tClient_Adresse.Adresse_ID=vAdresse.Adresse_ID
    	LEFT JOIN tMunicipalite ON tMunicipalite.Municipalite_ID = vAdresse.Municipalite_ID
    Bref là ce qui se passe c'est que tout ce qui est après la ligne du left join de tClient_Adresse est à NULL (c'est à dire : Adresse_Civique,Ville,tMunicipalite.Nom As Municipalite_Nom,Cd_Postal,Etat,Pays).

    Je sais ce qui ne fonctionne pas, je lui dis de faire un select TOP à l'intérieur du left join de vAdresse résultat je suppose qu'il a la dernière adresse en mémoire, mais vu qu'elle ne correspond jamais (sauf une chance sur le nombre d'enregistrements de tAdresse ) ça me met tout à nul.
    Mais voilà ma question : je sais que si j'enlève le TOP 1 de la ligne de vAdresse je n'ai plus de problème, mais je risque d'en avoir si le client a plusieurs adresses, mais moi je n'en veux qu'une seule!
    Comment faire?
    J'ai toujours des difficultés à faire ça... si vous pouviez m'aider à ce niveau ça sera extrèmement bien apprécié

  9. #9
    Membre éprouvé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2006
    Messages
    730
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 730
    Points : 923
    Points
    923
    Par défaut
    essaies un truc dans ce style plutot que de faire le select top dans le select primaire

    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
    SELECT TOP 100 tClient.Sexe,tClient.Nom,tClient.Prenom,Activite,Referent_Nom,tDossier.Dt_Debut,tDossier.Dt_Fin,
    Usager_Nom,tClient_Adresse.Adresse_ID,
    Adresse_Civique,Ville,tMunicipalite.Nom As Municipalite_Nom,Cd_Postal,Etat,Pays
            FROM tDossier 
            INNER JOIN tClient ON tClient.Client_ID = tDossier.Client_ID 
            INNER JOIN tActivite tA ON tA.Activite_ID = tDossier.Activite_ID 
            INNER JOIN tReferent tR ON tR.Referent_ID = tDossier.Referent_ID
            LEFT JOIN tClient_Adresse ON tClient.Client_ID = tClient_Adresse.Client_ID
            LEFT JOIN (SELECT TOP 1 Adresse_ID,Adresse_Civique,tAdresse.Ville,Municipalite_ID,Cd_Postal,Etat,Pays FROM 
            tAdresse ORDER BY Principal DESC)vAdresse ON tClient_Adresse.Adresse_ID=vAdresse.Adresse_ID
            LEFT JOIN tMunicipalite ON tMunicipalite.Municipalite_ID = vAdresse.Municipalite_ID
            INNER JOIN ((SELECT TOP 1 (Prenom + ' ' + Nom) As Usager_Nom FROM tDossier_Assistance tD_A 
            INNER JOIN tAssistance tA ON tD_A.Assistance_ID=tA.Assistance_ID 
            INNER JOIN tUsager ON tUsager.Usager_ID=tD_A.Usager_ID
            WHERE tA.Afficher_Sur_Rapport=1) A on A.Dossier_ID=tDossier.Dossier_ID
    Errare humanum est, perseverare diabolicum (Sénèque)

  10. #10
    Membre actif Avatar de MicaelFelix
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2006
    Messages
    254
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2006
    Messages : 254
    Points : 221
    Points
    221
    Par défaut
    Mais c'est pas ça mon problème, mon problème vient de l'adresse (je veux récupérer une seule adresse), les autres choses fonctionnent (j'ai testé séparément et je n'ai jamais eu d'ennui sur un select top dans le select principal).
    Une idée?

Discussions similaires

  1. Réunir des colonnes de tables différentes dans une requête
    Par GCAccess dans le forum Modélisation
    Réponses: 3
    Dernier message: 13/03/2009, 23h59
  2. Réponses: 2
    Dernier message: 23/04/2007, 00h10
  3. [Requete]Faire disparaître une colonne dans une requête
    Par emilie31 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 04/04/2007, 11h10
  4. Opération en colonne dans une requête
    Par mooh91 dans le forum Requêtes et SQL.
    Réponses: 12
    Dernier message: 10/02/2007, 05h07
  5. fusion de 2 colonnes dans une requête select?
    Par epeichette dans le forum Requêtes
    Réponses: 1
    Dernier message: 04/11/2005, 23h05

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