Warum funktionieren Platzhalter in GROUP BY-Anweisungen nicht?
29
Ich versuche, die folgende SQL-Anweisung zum Laufen zu bringen, erhalte jedoch einen Syntaxfehler:
SELECT A.*, COUNT(B.foo)FROM TABLE1 A
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY A.*
Hier ist A eine breite Tabelle mit 40 Spalten, und ich möchte nach Möglichkeit vermeiden, jeden Spaltennamen in der GROUP BY-Klausel aufzulisten. Ich habe viele solcher Tabellen, über die ich eine ähnliche Abfrage ausführen muss, sodass ich eine gespeicherte Prozedur schreiben muss. Wie kann man das am besten angehen?
Sie können dies umgehen, indem Sie eine Unterabfrage verwenden, nach der Sie gruppieren und dann beitreten:
SELECT A.*,COALESCE(B.cnt,0)AS Count_B_Foo
FROM TABLE1 AS A
LEFTJOIN(SELECT FKey, COUNT(foo)AS cnt
FROM TABLE2
GROUPBY FKey
)AS B
ON A.PKey = B.FKey ;
Es gibt eine Funktion in SQL-2003-Standard, die zulässt, dass in der SELECTListe Spalten enthalten sind, die nicht in der GROUP BYListe enthalten sind, sofern sie funktionsabhängig sind. Wenn diese Funktion in SQL-Server implementiert wurde, könnte Ihre Abfrage folgendermaßen lauten:
SELECT A.*, COUNT(B.foo)FROM TABLE1 A
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY A.pk --- the Primary Key of table A
Leider wurde dieses Feature noch nicht implementiert, auch nicht in der SQL-Server 2012-Version - und meines Wissens in keinem anderen DBMS. Mit Ausnahme von MySQL, das es nur unzureichend enthält (unzureichend als: Die obige Abfrage funktioniert, die Engine prüft jedoch nicht auf funktionale Abhängigkeiten, und andere falsch geschriebene Abfragen zeigen falsche, halbzufällige Ergebnisse an).
Können Sie ein paar RDBMS nennen, die diesen Teil des Standards wie geschrieben implementieren? Ich weiß zum Beispiel, dass MySQL können Sie (die richtigen Einstellungen angegeben) , um Elemente nicht innerhalb der Include - GROUP BYKlausel in der SELECTListe, aber es lässt es wie auf dem undefiniert Reihe dieser Wert aus kommen (so , wenn die Spalte oder den Ausdruck isn 't funktionell abhängig von der Gruppierung Ausdruck, dann könnte es aus jeder Zeile in der Gruppe kommen).
Adam Robinson
@Adam: Nein, ich kenne kein RDBMS, das es implementiert hat. MySQL hat es aber unzulänglich, wie Ihr Kommentar sagt.
ypercubeᵀᴹ
Erwischt. Ich habe tatsächlich gefragt, ob es welche gibt, da ich mit weitaus weniger RDBMS Erfahrung habe, als ich mir vorstellen würde, dass die meisten Leute, die Fragen auf dieser Site beantworten, dies hätten;) Aber das war mein Verdacht.
Adam Robinson
3
"und meines Wissens in keinem anderen DBMS." PostgreSQL 9.1 hat eine neue Funktion hinzugefügt, die für diesen Zweck entwickelt wurde. Es ist restriktiver als die Implementierung von MySQL.
Mark Byers
@MarkByers: Danke, das wusste ich nicht.
ypercubeᵀᴹ
24
Neben der Problemumgehung von @ ypercube ist "Tippen" nie eine Entschuldigung für die Verwendung SELECT *. Ich habe hier darüber geschrieben und denke, dass Ihre SELECTListe trotz der Problemumgehung immer noch die Spaltennamen enthalten sollte - auch wenn es eine massive Zahl wie 40 gibt.
Kurz gesagt, Sie können das Eingeben dieser großen Listen vermeiden, indem Sie im Objekt-Explorer auf den Spaltenknoten für das Objekt klicken und ihn in Ihr Abfragefenster ziehen. Der Screenshot zeigt eine Ansicht, aber das Gleiche kann für einen Tisch gemacht werden.
Aber wenn Sie mehr über die Gründe erfahren möchten, warum Sie sich dieser enormen Anstrengung unterziehen sollten, einen Gegenstand ein paar Zentimeter zu ziehen, lesen Sie bitte meinen Beitrag . :-)
In PostgreSQL (mit EMS SQL Manager) definiere ich eine Sicht als SELECT *und kopiere dann die Feldliste aus der Sichtdefinition.
Dezso
Ich bin mir sicher, dass SELECT *sollte nicht verwendet werden. Ich bin allerdings neugierig auf den GROUP BYFall. @Aaron, gibt es Effizienzprobleme mit 40 Spalten in der Liste "Gruppieren nach"?
ypercubeᵀᴹ
1
@ypercube - Soweit ich gesehen habe, ist es für die Syntax nur erforderlich A.PK, A.some, A.other, A.columns, some, other, columnsdies zu vergleichen , wenn Sie danach gruppieren .
Martin Smith
1
@datagod Entschuldigung, nein, Lücken konnten nur vom SSMS-Entwicklerteam erklärt werden. :-)
GROUP BY
Klausel in derSELECT
Liste, aber es lässt es wie auf dem undefiniert Reihe dieser Wert aus kommen (so , wenn die Spalte oder den Ausdruck isn 't funktionell abhängig von der Gruppierung Ausdruck, dann könnte es aus jeder Zeile in der Gruppe kommen).Neben der Problemumgehung von @ ypercube ist "Tippen" nie eine Entschuldigung für die Verwendung
SELECT *
. Ich habe hier darüber geschrieben und denke, dass IhreSELECT
Liste trotz der Problemumgehung immer noch die Spaltennamen enthalten sollte - auch wenn es eine massive Zahl wie 40 gibt.Kurz gesagt, Sie können das Eingeben dieser großen Listen vermeiden, indem Sie im Objekt-Explorer auf den Spaltenknoten für das Objekt klicken und ihn in Ihr Abfragefenster ziehen. Der Screenshot zeigt eine Ansicht, aber das Gleiche kann für einen Tisch gemacht werden.
Aber wenn Sie mehr über die Gründe erfahren möchten, warum Sie sich dieser enormen Anstrengung unterziehen sollten, einen Gegenstand ein paar Zentimeter zu ziehen, lesen Sie bitte meinen Beitrag . :-)
quelle
SELECT *
und kopiere dann die Feldliste aus der Sichtdefinition.SELECT *
sollte nicht verwendet werden. Ich bin allerdings neugierig auf denGROUP BY
Fall. @Aaron, gibt es Effizienzprobleme mit 40 Spalten in der Liste "Gruppieren nach"?A.PK, A.some, A.other, A.columns
,some, other, columns
dies zu vergleichen , wenn Sie danach gruppieren .