Die mehrteilige Kennung konnte nicht gebunden werden

196

Ich habe ähnliche Fehler bei SO gesehen, aber ich finde keine Lösung für mein Problem. Ich habe eine SQL-Abfrage wie:

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;

Wenn ich diese Abfrage ausführe, lautet das Fehlerergebnis: Die mehrteilige Kennung "a.maxa" konnte nicht gebunden werden. Warum?
P / s: Wenn ich die Abfrage in 2 einzelne Abfragen teile, läuft sie in Ordnung.

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;

und

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;
PhamMinh
quelle
Enthält die phuongxaTabelle eine Spalte maxa?
Michael Petrotta
1
Was passiert, wenn Sie eine Gruppe von maxa, tong hinzufügen - direkt nach dem 5. September 2011.
user710502
Ja es hat. Wenn ich die Abfrage auf 2 Unterabfragen aufteile, läuft sie in
Ordnung
Klingt so, als würden Sie auf der falschen Datenbank ausführen. Fügen Sie am Anfang der Abfrage eine Anweisung "USE [Datenbankname]" hinzu und prüfen Sie, ob der Fehler weiterhin angezeigt wird.
Brian
1
Nein, ich hatte oben gesagt, wenn ich die Abfrage in zwei einzelne Abfragen teile, läuft sie okey.
PhamMinh

Antworten:

226

Sie mischen implizite Verknüpfungen mit expliziten Verknüpfungen. Das ist erlaubt, aber Sie müssen wissen, wie man das richtig macht.

Die Sache ist, dass explizite Verknüpfungen (diejenigen, die mit dem JOINSchlüsselwort implementiert werden ) Vorrang vor impliziten Verknüpfungen haben (die 'Komma'-Verknüpfungen, bei denen die Verknüpfungsbedingung in der WHEREKlausel angegeben ist).

Hier ist ein Überblick über Ihre Anfrage:

SELECT
  
FROM a, b LEFT JOIN dkcd ON 
WHERE 

Sie erwarten wahrscheinlich, dass es sich so verhält:

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

das heißt, die Kombination von Tabellen aund bwird mit der Tabelle verbunden dkcd. In der Tat ist was passiert

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

Das heißt, wie Sie vielleicht bereits verstanden haben, dkcdwird spezifisch gegen bund nur bdann verbunden, dann wird das Ergebnis des Joins amit der WHEREKlausel kombiniert und weiter gefiltert . In diesem Fall ist ein Verweis ain der ONKlausel ungültig und azu diesem Zeitpunkt unbekannt. Deshalb erhalten Sie die Fehlermeldung.

Wenn ich Sie wäre, würde ich wahrscheinlich versuchen, diese Abfrage neu zu schreiben, und eine mögliche Lösung könnte sein:

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

Hier werden zuerst die Tabellen aund bzusammengefügt, dann wird das Ergebnis mit verbunden dkcd. Grundsätzlich ist dies dieselbe Abfrage wie bei Ihnen, wobei nur eine andere Syntax für einen der Joins verwendet wird. Dies macht einen großen Unterschied: Die Referenz a.maxain der dkcdJoin-Bedingung des Joins ist jetzt absolut gültig.

Wie @Aaron Bertrand richtig bemerkt hat, sollten Sie sich wahrscheinlich maxamit einem bestimmten Alias ​​qualifizieren, wahrscheinlich ain der ORDER BYKlausel.

Andriy M.
quelle
ORDER BY maxa ist immer noch nicht eindeutig, oder? Außerdem würde ich mit dem Datum "1. September 2011" vorsichtig sein und nicht mit verschiedenen Sprach- / Regionaleinstellungen arbeiten.
Aaron Bertrand
@ Aaron: Stimme zu ORDER BY maxa, danke. Ich glaube, die OP hat die Daten so ausgewählt, um sie in ihrer Umgebung anzugeben.
Andriy M
"explizite Verknüpfungen ... haben Vorrang vor impliziten" - können Sie dies bitte zitieren? Ist das beispielsweise in SQL-Standards definiert oder handelt es sich um eine Produktfunktion? Vielen Dank.
Tag, wenn
1
@onedaywhen: Ich fürchte, dies ist bisher nur eine Beobachtung auf meiner Seite. Ich bin etwas erleichtert darüber, dass ich hier nicht als Erster über den Vorrang von Joins spreche , aber ansonsten würde ich mich freuen, selbst eine offizielle Bestätigung zu finden.
Andriy M
1
In meinem Fall habe ich vergessen, Leerzeichen einzufügen, als ich Zeichenfolgen zum Erstellen des SQL verkettet habe, sodass 'FROM dbo.table_a a' + 'INNER JOIN dbo.table_b b' zu 'FROM dbo.table_a aINNER JOIN dbo.table_b b' wurde. und es wurde verwirrt und gab mir diese Fehlermeldung. Details, Details, Details.
Guy Schalnat
40

Manchmal tritt dieser Fehler auf, wenn Sie Ihr Schema (dbo) in Ihrer Abfrage falsch verwenden.

Zum Beispiel, wenn Sie schreiben:

select dbo.prd.name
from dbo.product prd

Sie erhalten den Fehler.

In diesen Situationen ändern Sie es zu:

select prd.name
from dbo.product prd
Bobs
quelle
1
Das ist ziemlich nervig und hat viel zu lange gedauert, um es herauszufinden. Danke. Nervigste Teil ist es manchmal über diese naggs aber auch andere Zeiten es geht normaly
DanteTheSmith
12

Wenn Sie Alies einen Namen gegeben haben, ändern Sie diesen in den tatsächlichen Namen

beispielsweise

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;

ändere das auf

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;
Alexander Zaldostanov
quelle
1
Achten Sie auch beim Aufbau der SQL-Zeichenfolge darauf, dass am Ende der Zeile keine Leerzeichen stehen. Es hat meinen Alias ​​M in MINNER konvertiert, als es in die nächste Zeile INNER JOIN unten aufgenommen wurde. Der SQL-Profiler, der die ausgeführte Zeichenfolge anzeigt, hat zur Lösung meines Problems beigetragen. (Kommentiert hier, da es sich um das Problem mit dem Alias ​​v des tatsächlichen Namens handelt)
Simon
wow @Simon danke, ich habe nicht einmal darüber nachgedacht und meinen Kopf gegen die Wand geschlagen, um herauszufinden, warum meine Abfrage nicht funktioniert hat. Mir fehlte ein Leerzeichen am Ende eines der String-Wagenrückläufe!
Buradd
9

Ich hatte Probleme mit der gleichen Fehlermeldung in SQL SERVER, da ich mehrere Joins hatte. Durch Ändern der Reihenfolge der Joins wurde dies für mich behoben.

Pavel M.
quelle
3

In meinem Fall stellte sich heraus, dass es sich um den Aliasnamen handelte, den ich der Tabelle gegeben hatte. "oa" scheint für SQL Server nicht akzeptabel zu sein.

Hashim Akhtar
quelle
2

Ich hatte den gleichen Fehler von JDBC. Überprüfte alles und meine Anfrage war in Ordnung. Es stellte sich heraus, in wo Klausel ich ein Argument habe:

where s.some_column = ?

Und der Wert des von mir übergebenen Arguments war null. Dies führt auch zu dem gleichen Fehler, der irreführend ist, da Sie beim Durchsuchen des Internets feststellen, dass etwas mit der Abfragestruktur nicht stimmt, aber in meinem Fall nicht. Ich dachte nur, jemand könnte das gleiche Problem haben

xbmono
quelle
2

Für mich hat es funktioniert, meine WHERE-Klausel in eine SELECT-Unterabfrage zu ändern

VON:

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

ZU:

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

Ich bin neu in SQL, bin jedoch in einem Kurs auf dieses Problem gestoßen und habe festgestellt, dass das Zuweisen der Abfrage zum Projekt speziell dazu beigetragen hat, den mehrteiligen Fehler zu beseitigen. Das von mir erstellte Projekt war beispielsweise CTU SQL Project. Daher habe ich sichergestellt, dass ich mein Skript mit USE [CTU SQL Project] als erste Zeile wie unten gestartet habe.

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.
Bogartz
quelle
1
Wenn Sie "Projekt" sagen, meinen Sie Datenbank und nicht Projektion. Die use-Anweisung ändert einfach, auf welche Datenbank Sie die Abfrage
anwenden
Ja, Charleh-Projekt wie in der Datenbank, in der ich gearbeitet habe. Ich war mir nicht sicher, was ich mit meiner Datenbank falsch gemacht habe, aber die Angabe von "use" und der spezifischen Datenbank für den Umfang beseitigte meinen Fehler.
Bogartz
1

Wenn dieser Fehler in einem UPDATEauftritt, überprüfen Sie die JOINTabelle mit der Spalte / dem Feld, die den Fehler verursacht.

In meinem Fall war dies auf das Fehlen des JOINSelbst zurückzuführen, das aufgrund eines unbekannten Feldes denselben Fehler erzeugte (wie Andriy betonte ).

CPHPython
quelle
1

Stattdessen können Sie versuchen, Tabellen wie:

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

Das sollte funktionieren

Suman Kumar
quelle
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;
SVaidya
quelle
Verwenden Sie die Tabellennamen selbst anstelle des Alias, wenn ein mehrteiliges Problem auftritt.
SVaidya
1

Mein Fehler war, ein Feld zu verwenden, das in der Tabelle nicht vorhanden war.

table1.field1 => ist nicht vorhanden

table2.field1 => ist korrekt

Korrigieren Sie Ihren Tabellennamen.

Mein Fehler ist aufgrund der Verwendung von WITH aufgetreten

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

bei Verwendung in Verbindung mit anderen Tabellen ...

Zolfaghari
quelle
1

Haben Sie vergessen, einige Tische zu verbinden? Wenn nicht, müssen Sie wahrscheinlich einige Aliase verwenden.

Tadej
quelle
1

Ich hatte auch mit diesem Fehler zu kämpfen und hatte die gleiche Strategie wie die Antwort. Ich füge meine Antwort hinzu, um zu bestätigen, dass dies eine Strategie ist, die funktionieren sollte.

Hier ist ein Beispiel, in dem ich zuerst einen inneren Join zwischen zwei Tabellen mache, von denen ich weiß, dass sie Daten haben, und dann zwei linke äußere Joins für Tabellen, die möglicherweise entsprechende Zeilen haben, die leer sein können. Sie mischen innere Verknüpfungen und äußere Verknüpfungen, um Ergebnisse mit Daten über Tabellen hinweg zu erhalten, anstatt die durch Kommas getrennte Standardsyntax zwischen Tabellen auszuführen und Zeilen in der gewünschten Verknüpfung zu verpassen.

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]%')

Erstens: Führen Sie die inneren Verknüpfungen zwischen Tabellen durch, für die eine Datenübereinstimmung erwartet wird. Zweiter Teil: Fahren Sie mit den äußeren Verknüpfungen fort, um zu versuchen, Daten in anderen Tabellen abzurufen. Dies filtert jedoch nicht Ihre Ergebnismenge heraus, wenn die äußere Verknüpfung der Tabelle zu keine entsprechenden Daten enthält oder mit der Bedingung übereinstimmt, die Sie im Prädikat / der Bedingung on eingerichtet haben.

Tore Aurstad
quelle
0

Dieser Fehler kann auch durch einfaches Fehlen eines Kommas verursacht werden , zwischen den Spaltennamen in der SELECT-Anweisung .

z.B:

SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
Andrew
quelle