L'identificatore multiparte non può essere associato


196

Ho visto errori simili su SO, ma non trovo una soluzione al mio problema. Ho una query SQL come:

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;

Quando eseguo questa query, il risultato dell'errore è: Impossibile identificare l'identificatore in più parti "a.maxa". Perché?
P / s: se divido la query in 2 query singole, funziona bene.

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;

e

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

La phuongxatabella include una colonna maxa?
Michael Petrotta,

1
Cosa succede se aggiungi gruppo per maxa, tong - subito dopo il 5 settembre 2011.
user710502

Sì sì. Se divido la query in 2 subquery, viene eseguita
correttamente

Sembra che tu stia eseguendo il database sbagliato. Aggiungi un'istruzione "USE [nome database]" all'inizio della query e verifica se l'errore persiste.
Brian

1
No, avevo detto sopra, se divido la query in 2 query singole, viene eseguito okey.
PhamMinh,

Risposte:


226

Stai mescolando join impliciti con join espliciti. Ciò è consentito, ma è necessario essere consapevoli di come farlo correttamente.

Il fatto è che i join espliciti (quelli implementati utilizzando la JOINparola chiave) hanno la precedenza su quelli impliciti (i join 'virgola', dove la condizione di join è specificata nella WHEREclausola).

Ecco uno schema della tua query:

SELECT
  
FROM a, b LEFT JOIN dkcd ON 
WHERE 

Probabilmente ti aspetti che si comporti in questo modo:

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

cioè, la combinazione di tabelle aed bè unita alla tabella dkcd. In effetti, ciò che sta accadendo è

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

cioè, come avrete già capito, dkcdviene unito in modo specifico bsolo e solo b, quindi il risultato del join viene combinato ae filtrato ulteriormente con la WHEREclausola. In questo caso, qualsiasi riferimento a anella ONclausola non è valido, non aè noto a quel punto. Questo è il motivo per cui ricevi il messaggio di errore.

Se fossi in te, probabilmente proverei a riscrivere questa query e una possibile soluzione potrebbe essere:

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

Qui le tabelle ae bvengono unite per prime, quindi il risultato viene unito dkcd. Fondamentalmente, questa è la stessa query della tua, usando solo una sintassi diversa per uno dei join, il che fa una grande differenza: il riferimento a.maxanella dkcdcondizione di join è ora assolutamente valido.

Come ha notato correttamente @Aaron Bertrand, dovresti probabilmente qualificarti maxacon un alias specifico, probabilmente a, nella ORDER BYclausola.


ORDER BY maxa è ancora ambiguo, no? Inoltre starei attento con '1 settembre 2011' come una data, non funzionerà con impostazioni diverse lingua / regionali.
Aaron Bertrand,

@Aaron: d'accordo ORDER BY maxa, grazie. Per quanto riguarda le date, credo che l'OP abbia scelto di specificarle nel loro ambiente.
Andriy M,

"join espliciti ... hanno la precedenza su quelli impliciti" - puoi fornire una citazione per questo, per favore? ad esempio, è definito negli standard SQL o è una funzionalità del prodotto? Grazie.
giorno

1
@onedaywhen: temo che finora non sia altro che un'osservazione dalla mia parte. Sono un po 'sollevato dal fatto che non sarò il primo a parlare della precedenza dei join qui, ma a parte questo, sarei felice di trovare personalmente qualsiasi tipo di conferma ufficiale.
Andriy M,

1
Nel mio caso, stavo dimenticando di inserire spazi quando ho concatenato stringhe per costruire sql, quindi 'FROM dbo.table_a a' + 'INNER JOIN dbo.table_b b' è diventato 'FROM dbo.table_a aINNER JOIN dbo.table_b b', e si è confuso e mi ha dato questo messaggio di errore. Dettagli, dettagli, dettagli.
Guy Schalnat,

40

A volte questo errore si verifica quando si utilizza lo schema (dbo) nella query in modo errato.

per esempio se scrivi:

select dbo.prd.name
from dbo.product prd

otterrai l'errore.

In queste situazioni, cambiarlo in:

select prd.name
from dbo.product prd

1
Questo è abbastanza fastidioso e mi ci è voluto troppo tempo per capirlo. Grazie. La parte più fastidiosa a volte è fastidiosa per questo, ma altre volte passa normalmente
DanteTheSmith

12

se hai dato il nome alies, cambialo in nome reale

per esempio

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;

cambialo in

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

1
Inoltre, se stai costruendo la stringa sql, fai attenzione alla mancanza di spazi finali alla fine della linea. Ha convertito il mio alias M in MINNER quando si è unito alla successiva riga INNER JOIN di seguito. Il profiler SQL che mostra la stringa eseguita mi ha aiutato a risolvere il mio problema. (Commentato qui in quanto correlato al problema relativo al nome reale alias)
Simon

wow @Simon grazie non ci ho nemmeno pensato e ho sbattuto la testa contro il muro cercando di capire perché la mia domanda non funzionava, mi mancava uno spazio alla fine di uno dei ritorni del carrello della stringa!
Buradd,

9

Ho avuto difficoltà con lo stesso messaggio di errore in SQL SERVER, poiché avevo più join, modificando l' ordine dei join risolto per me.


3

Nel mio caso il problema si è rivelato essere il nome alias che avevo dato alla tabella. "o" sembra non essere accettabile per SQL Server.


2

Stavo avendo lo stesso errore da JDBC. Ho controllato tutto e la mia domanda andava bene. Si è scoperto, in cui la clausola ho un argomento:

where s.some_column = ?

E il valore dell'argomento che stavo trasmettendo era nullo. Questo dà anche lo stesso errore che è fuorviante perché quando si cerca in Internet si finisce che qualcosa non va nella struttura della query, ma non è nel mio caso. Ho pensato che qualcuno potesse affrontare lo stesso problema


2

Quello che ha funzionato per me è stato cambiare la mia clausola WHERE in una sottoquery SELECT

A PARTIRE DAL:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = [dbo].FetchedTagTransferData.IssueId

PER:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)

1

Sono nuovo di SQL, ma ho riscontrato questo problema in un corso che stavo seguendo e ho scoperto che l'assegnazione della query al progetto ha contribuito in modo specifico all'eliminazione dell'errore in più parti. Ad esempio, il progetto che ho creato era CTU SQL Project, quindi mi sono assicurato di aver avviato il mio script con USE [CTU SQL Project] come prima riga come di seguito.

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.

1
Quando dici "progetto" presumo tu intenda il database e non la proiezione. L'istruzione use modifica semplicemente il database in cui si sta eseguendo l'ambito della query
Charleh

Sì, progetto Charleh come nel database su cui stavo lavorando. Non ero sicuro di quello che stavo facendo di sbagliato con il mio database, ma affermando che "uso" e il database specifico per ambito hanno eliminato il mio errore.
Bogartz,

1

Se questo errore si verifica in un UPDATE, ricontrolla JOINsu nella tabella con la colonna / campo che causa l'errore.

Nel mio caso ciò è dovuto alla mancanza di JOINse stesso, che ha generato lo stesso errore a causa di un campo sconosciuto (come sottolineato da Andriy ).


1

Puoi invece provare a unire tabelle come,

select 
  .... 
from 
   dkcd 
     right join 
                a
                  , b

Questo dovrebbe funzionare


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

Utilizzare i nomi delle tabelle stessi invece di utilizzare l'alias se si verifica un problema associato a più parti.
SVaidya,

1

Il mio errore era usare un campo che non esisteva nella tabella.

table1.field1 => non esiste

table2.field1 => è corretto

Correggi il nome della tabella.

il mio errore si è verificato a causa dell'utilizzo di WITH

WITH RCTE AS (
   SELECT...
)
SELECT RCTE.Name, ...
FROM 
  RCTE INNER JOIN Customer
  ON RCTE.CustomerID = Customer.ID 

se utilizzato in join con altre tabelle ...


1

Hai dimenticato di unirti ad alcuni tavoli? In caso contrario, probabilmente è necessario utilizzare alcuni alias.


1

Stavo anche lottando con questo errore e ho finito con la stessa strategia della risposta. Includo la mia risposta solo per confermare che questa è una strategia che dovrebbe funzionare.

Ecco un esempio in cui eseguo prima un join interno tra due tabelle che conosco i dati e quindi due join esterni a sinistra su tabelle che potrebbero avere righe corrispondenti che possono essere vuote. Mescoli i join interni e i join esterni per ottenere risultati con i dati in tutte le tabelle invece di eseguire la sintassi separata da virgola predefinita tra le tabelle e perdere le righe nel join desiderato.

use somedatabase
go 

select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram,  o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o 
inner join patient p on o.operationid = p.operationid 
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')

Primo: esegui i join interni tra le tabelle che prevedi corrispondano ai dati. Seconda parte: continuare con i join esterni per tentare di recuperare i dati in altre tabelle, ma ciò non filtrerà il set di risultati se il join esterno della tabella non ha dati corrispondenti o corrisponde alla condizione impostata nel predicato / condizione.


0

Questo errore può anche essere causato dalla mancanza di una virgola ,tra i nomi delle colonne nell'istruzione SELECT.

per esempio:

SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.