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
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY 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?

Ich benutze MS SQL Server 2008.

Antworten:


32

GROUP BY A.* ist in SQL nicht erlaubt.

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
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY 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
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY 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).

Wie @Mark Byers uns in einem Kommentar mitteilte, hat PostgreSQL 9.1 eine neue Funktion hinzugefügt, die für diesen Zweck entwickelt wurde. Es ist restriktiver als die Implementierung von MySQL.


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.

Bildbeschreibung hier eingeben

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. :-)
Aaron Bertrand

1
@ Pacerier Entschuldigung, ich bin nicht ganz einverstanden , aber vielleicht könntest du das näher erläutern.
Aaron Bertrand
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.