237 votes

L'identifiant en plusieurs parties n'a pas pu être lié

J'ai vu des erreurs similaires sur SO, mais je ne trouve pas de solution à mon problème. J'ai une requête SQL comme :

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa a ,
        quanhuyen b
        LEFT OUTER JOIN ( SELECT    maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  maxa
                        ) AS dkcd ON dkcd.maxa = a.maxa
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

Lorsque j'exécute cette requête, le résultat de l'erreur est : L'identifiant en plusieurs parties "a.maxa" n'a pas pu être lié. Pourquoi ?
P/s : si je divise la requête en 2 requêtes individuelles, cela fonctionne bien.

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen
FROM    phuongxa a ,
        quanhuyen b
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

y

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;

0 votes

Est-ce que le phuongxa le tableau comprend une colonne maxa ?

1 votes

Que se passe-t-il si vous ajoutez le groupe par maxa, tong -- juste après le 5 septembre 2011.

0 votes

Oui, c'est le cas. Si je divise la requête en deux sous-requêtes, elle fonctionne bien.

275voto

Andriy M Points 40395

Vous mélangez des jointures implicites avec des jointures explicites. C'est autorisé, mais vous devez savoir comment le faire correctement.

En fait, les jointures explicites (celles qui sont mises en œuvre à l'aide de la fonction JOIN ) sont prioritaires par rapport aux jointures implicites (les jointures "à virgule", où la condition de jointure est spécifiée dans le mot-clé WHERE clause).

Voici un aperçu de votre requête :

SELECT
  …
FROM a, b LEFT JOIN dkcd ON …
WHERE …

Vous vous attendez probablement à ce qu'il se comporte de cette manière :

SELECT
  …
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …

c'est-à-dire la combinaison de tableaux a y b est joint à la table dkcd . En fait, ce qui se passe est

SELECT
  …
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …

c'est-à-dire, comme vous l'avez peut-être déjà compris, dkcd est joint spécifiquement contre b et seulement b puis le résultat de la jointure est combiné avec a et filtré davantage avec le WHERE clause. Dans ce cas, toute référence à a dans le ON est invalide, a est inconnu à ce moment-là. C'est pourquoi vous obtenez le message d'erreur.

Si j'étais vous, j'essaierais probablement de réécrire cette requête, et une solution possible pourrait être :

SELECT DISTINCT
  a.maxa,
  b.mahuyen,
  a.tenxa,
  b.tenhuyen,
  ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
  INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
  LEFT OUTER JOIN (
    SELECT
      maxa,
      COUNT(*) AS tong
    FROM khaosat
    WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
    GROUP BY maxa
  ) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
ORDER BY a.maxa

Voici les tableaux a y b sont joints en premier, puis le résultat est joint à dkcd . Fondamentalement, il s'agit de la même requête que la vôtre, mais avec une syntaxe différente pour l'une des jointures, ce qui fait une grande différence : la référence a.maxa dans le dkcd La condition de jonction de l'entreprise est maintenant absolument valide.

Comme @Aaron Bertrand l'a correctement noté, vous devriez probablement qualifier maxa avec un alias spécifique, probablement a dans le ORDER BY clause.

0 votes

ORDER BY maxa est toujours ambigu, non ? Je serais également prudent avec 'Sep 1 2011' comme date, cela ne fonctionnera pas avec des paramètres de langue/région différents.

0 votes

@Aaron : D'accord sur ORDER BY maxa Merci. En ce qui concerne les dates, je crois que c'est ainsi que le PO a choisi de les spécifier dans son environnement.

0 votes

"les jointures explicites... ont la priorité sur les jointures implicites" - pouvez-vous fournir une citation à ce sujet, s'il vous plaît ? Par exemple, est-ce défini dans les normes SQL ou est-ce une fonctionnalité du produit ? Merci.

50voto

breceivemail Points 8024

Parfois, cette erreur se produit lorsque vous utilisez votre schéma (dbo) dans votre requête d'une manière incorrecte.

par exemple si vous écrivez :

select dbo.prd.name
from dbo.product prd

vous obtiendrez l'erreur.

Dans cette situation, changez-le en :

select prd.name
from dbo.product prd

2 votes

C'est assez ennuyeux et ça m'a pris beaucoup trop de temps pour le découvrir. Merci. Le plus ennuyeux, c'est que parfois ça me harcèle, mais d'autres fois ça passe normalement.

20voto

Sallu_Mia Points 106

Si vous avez donné le nom d'alies changez-le pour le nom réel

par exemple

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  [LoginInfo].[dbo].[TableA].name=[LoginInfo].[dbo].[TableB].name;

changez cela en

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;

14voto

Pavel M. Points 230

Je me débattais avec le même message d'erreur dans SQL SERVER, puisque j'avais plusieurs jointures, en changeant le ordre des jointures a résolu le problème pour moi.

6voto

Hashim Akhtar Points 66

Dans mon cas, le problème s'est avéré être le nom d'alias que j'avais donné à la table. "oa" semble ne pas être acceptable pour SQL Server.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X