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 multipartite "a.maxa" ; n'a pas pu être lié. Pourquoi ?
P/s : si je divise la requête en 2 requêtes individuelles, elle s'exécute correctement.
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;
et
SELECT maxa ,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
AND 'Sep 5 2011'
GROUP BY maxa;
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 implémentées à l'aide du mot-clé JOIN
) sont prioritaires sur les jointures implicites (les jointures à la 'virgule' ; où la condition de jointure est spécifiée dans la clause WHERE
).
Voici un aperçu de votre requête :
SELECT
…
FROM a, b LEFT JOIN dkcd ON …
WHERE …
Vous vous attendez probablement à ce qu'elle se comporte comme ceci :
SELECT
…
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …
c'est-à-dire que la combinaison des tables a
et b
est jointe à la table dkcd
. En fait, ce qui se passe, c'est que
SELECT
…
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …
c'est-à-dire, comme vous l'avez peut-être déjà compris, que dkcd
est joint spécifiquement à b
et seulement b
, puis le résultat de la jointure est combiné à a
et filtré davantage avec la clause WHERE
. Dans ce cas, toute référence à a
dans la clause ON
est invalide, a
étant 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
Ici, les tables a
et b
sont jointes en premier, puis le résultat est joint à dkcd
. En fait, c'est 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 la condition de jointure de dkcd
's est maintenant absolument valide.
Comme @Aaron Bertrand l'a correctement noté, vous devriez probablement qualifier maxa
avec un alias spécifique, probablement a
, dans la clause ORDER BY
.
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 suivante.
Dans ce cas, changez-le en :
select prd.name
from dbo.product prd
Je suis novice en SQL, mais j'ai rencontré ce problème dans le cadre d'un cours que je suivais et j'ai découvert que le fait d'attribuer la requête au projet spécifique permettait d'éliminer l'erreur en plusieurs parties. Par exemple, le projet que j'ai créé était le projet SQL CTU. Je me suis donc assuré de commencer mon script avec USE [Projet SQL CTU] comme première ligne, comme ci-dessous.
USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.