Den flerdelte identifikatoren kunne ikke bindes

Jeg har sett lignende feil på SO, men jeg finner ikke en løsning på problemet mitt. Jeg har en SQL-spørring som:

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;

Når jeg utfører denne spørringen, er feilresultatet: Den flerdelte identifikatoren "a.maxa" kunne ikke bindes. Hvorfor?
P / s: Hvis jeg deler spørringen i 2 individuelle spørringer, kjører den ok.

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;

og

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

Du blander implisitte sammenføyninger med eksplisitte sammenføyninger. Det er tillatt, men du må være klar over hvordan du gjør det på riktig måte.

Saken er at eksplisitte sammenføyninger (de som er implementert ved hjelp av nøkkelordet JOIN) har forrang over implisitte ('komma' sammenføyninger, der sammenføyningsbetingelsen er spesifisert i WHERE -klausulen).

Her er en oversikt over spørringen din:

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

Du forventer sannsynligvis at det skal oppføre seg slik:

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

det vil si at kombinasjonen av tabellene a og b slås sammen med tabellen dkcd. Det som faktisk skjer, er følgende

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

det vil si, som du kanskje allerede har forstått, dkcd er sammenføyd spesifikt mot b og bare b, deretter kombineres resultatet av sammenføyningen med a og filtreres videre med WHERE-klausulen. I dette tilfellet er enhver referanse til a i ON-klausulen ugyldig, a er ukjent på det tidspunktet. Det er derfor du får feilmeldingen.

Hvis jeg var deg, ville jeg sannsynligvis prøve å omskrive denne spørringen, og en mulig løsning kan være:

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

Her sammenføyes tabellene a og b først, deretter sammenføyes resultatet til dkcd. I utgangspunktet er dette den samme spørringen som din, bare med en annen syntaks for en av sammenføyningene, noe som utgjør en stor forskjell: referansen a.maxa i dkcd's sammenføyningsbetingelse er nå absolutt gyldig.

Som @Aaron Bertrand riktig har bemerket, bør du sannsynligvis kvalifisere maxa med et bestemt alias, sannsynligvis a, i ORDER BY klausulen.

Kommentarer (9)

Noen ganger oppstår denne feilen når du bruker skjemaet (dbo) i spørringen på feil måte.

for eksempel hvis du skriver:

select dbo.prd.name
from dbo.product prd

vil du få feilen.

I disse situasjonene endrer du det til:

select prd.name
from dbo.product prd
Kommentarer (1)

Jeg er ny i SQL, men kom over dette problemet i et kurs jeg tok og fant ut at å tilordne spørringen til prosjektet spesifikt bidro til å eliminere feilen i flere deler. For eksempel var prosjektet jeg opprettet CTU SQL Project, så jeg sørget for at jeg startet skriptet mitt med USE [CTU SQL Project] som min første linje som nedenfor.

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.
Kommentarer (2)