Warum SQL mich zwingen, alle nicht aggregierte Felder aus meiner SELECT-Klausel in meinem GROUP BY-Klausel zu wiederholen? [geschlossen]

StackOverflow https://stackoverflow.com/questions/416625

  •  03-07-2019
  •  | 
  •  

Frage

Das hat mich für eine lange Zeit abgehört.

99% der Zeit, ist die GROUP BY-Klausel eine exakte Kopie der SELECT-Klausel, abzüglich der Aggregatfunktionen (MAX, SUM, etc.).
Dies bricht die Sie Repeat Yourself-Prinzip nicht.

Wann kann die GROUP BY-Klausel nicht eine exakte Kopie der SELECT-Klausel enthält, abzüglich die Aggregatfunktionen?

Bearbeiten

Ich weiß, dass einige Implementierungen können Sie verschiedene Felder in der GROUP BY haben, als in der SELECT (also 99%, nicht 100%), aber das ist sicherlich eine sehr geringe Ausnahme?
Kann jemand erklären, was zurückgegeben werden soll, wenn Sie verschiedene Felder verwenden?

Danke.

War es hilfreich?

Lösung

Ich neige dazu, mit Ihnen zu vereinbaren - das ist eine von vielen Fällen, in denen SQL sollte etwas schlauer Standardwerte haben uns alle etwas Tipp zu speichern. Zum Beispiel vorstellen, wenn diese legal waren:

Select ClientName, InvoiceAmount, Sum(PaymentAmount) Group By *

wobei „*“ bedeutet „alle Nicht-Aggregatfelder“. Wenn jeder wusste, das ist, wie es funktioniert, dann gäbe es keine Verwirrung. Sie könnten Unter in einer bestimmten Liste von Feldern, wenn Sie etwas heikel, aber die Splat bedeutet „alle‚em“(das bedeutet in diesem Zusammenhang, alle möglich sind) machen wollte.

Zugegeben, „*“ bedeutet etwas anderes als in der SELECT-Klausel, also vielleicht ein anderes Zeichen besser funktionieren würde:

Select ClientName, InvoiceAmount, Sum(PaymentAmount) Group By !

Es gibt ein paar andere Bereiche wie die, wo SQL einfach nicht so eloquent ist, wie es sein könnte. Aber an diesem Punkt, ist es wahrscheinlich zu verschanzt viele große Änderungen dieser Art zu machen.

Andere Tipps

Weil sie zwei verschiedene Dinge sind, können Sie Gruppe durch Gegenstände, die nicht in der select-Klausel sind

EDIT:

Auch ist es sicher, dass die Annahme zu machen?

Ich habe eine SQL-Anweisung

Select ClientName, InvAmt, Sum(PayAmt) as PayTot

Ist es „richtige“ für den Server von Client UND InvoiceAmount gruppieren möchte, anzunehmen, ich? Ich persönlich bevorzuge (und denke, es ist sicherer) diesen Code zu haben,

Select ClientName, InvAmt, Sum(PayAmt) as PayTot
Group By ClientName

wirft einen Fehler, mich auffordert, den Code zu ändern

Select ClientName, Sum(InvAmt) as InvTot, Sum(PayAmt) as PayTot
Group By ClientName

Ich hoffe, / erwarten wir bald etwas umfassender sehen; eine SQL-Geschichtsstunde zum Thema wäre nützlich und informativ sein. Jemand? Jemand? Bueller?

In der Zwischenzeit kann ich folgendes beachten:

SQL schon vor dem DRY-Prinzip, zumindest soweit es dokumentiert wurde in Der Pragmatische Programmierer .

Nicht alle DBs erfordern die vollständige Liste: Sybase, zum Beispiel, wird gerne Abfragen ausführen wie

SELECT a, b, COUNT(*)
FROM some_table
GROUP BY a

..., die (zumindest jedes Mal, wenn ich so ein Monster aus Versehen lief) oft so enorme unbeabsichtigte Cord-Sets führt, dass panische Anfragen schnell erfolgen, die DBAs Betteln um den Server prallen. Das Ergebnis ist eine Art Teil cartesianischen Produkts, aber ich denke, es ist meist ein Fehler auf Sybase Teil sein kann richtig den SQL-Standard zu implementieren.

Vielleicht brauchen wir eine Kurzform - nennen es Group

GroupSelect Field1, Field2, sum(Field3) From SomeTable Where (X = "3")

Auf diese Weise muss der Parser nur einen Fehler aus, wenn Sie eine Aggregatfunktion auslassen.

Der Grund dafür ist, dass Sie falsche Ergebnisse häufiger als nicht bekommen würden, wenn Sie nicht alle Spalten angegeben haben. Angenommen, Sie haben drei Spalten, col1, col2 und col3.

Ihre Daten Angenommen, sieht wie folgt aus:

Col1  Col2 Col3
a      b    1
a      c    1
b      b    2
a      b    3

select col1, col2, sum(col3) from mytable group by col1, col2
würde die folgenden Ergebnisse liefern:

Col1  Col2 Col3
a      b    4
a      c    1
b      b    2

Wie wäre es interpretieren
select col1, col2, sum(col3) from mytable group by col1

Meine Vermutung wäre,

Col1  Col2 Col3
a      b    5
a      c    5
b      b    2

Dies sind eindeutig schlechte Ergebnisse. Verlauf Je komplexer die Abfrage und desto mehr tritt desto weniger wahrscheinlich, dass die Abfrage korrekte Ergebnisse zurückkehren würde oder dass der Programmierer würde auch wissen, ob sie falsch waren.

sein würde

Ich persönlich bin froh, dass group by die Felder erfordert.

Ich stimme mit GROUP BY ALL, GROUP BY *, oder etwas ähnliches. Wie in der ursprünglichen Post erwähnt, in 99% (vielleicht) der Fälle mögen Sie gruppieren von allen Nicht-Aggregat-Spalten / Ausdrücke.

Hier ist jedoch ein Beispiel, wo Sie GROUP BY Spalten benötigen würden, aus Gründen der Abwärtskompatibilitätsgründen.

SELECT 
  MIN(COUNT(*)) min_same_combination_cnt, 
  MAX(COUNT(*)) max_same_comb_cnt, 
  AVG(COUNT(*)) avg_same_comb_cnt, 
  SUM(COUNT(*)) total_records,
  COUNT(COUNT(*)) distinct_combinations_cnt
FROM <some table>
GROUP BY <list of columns>

Das funktioniert in Oracle. Ich benutze es Selektivität auf Säulen zu schätzen. Die Gruppe, die durch an die innere Aggregatfunktion angewendet. Dann wird die äußere Aggregat angewendet wird.

Es wäre schön, einen Vorschlag für diese Verbesserung auf dem SQL-Standard vorzubringen. Ich weiß nur nicht, wie das funktioniert.

Eigentlich wäre das nicht 100% der Zeit sein? Gibt es einen Fall, in dem Sie eine (nicht-Aggregat) Spalte in der Auswahl haben kann, die nicht in der GROUP BY ist?

ich eine Antwort nicht obwohl haben. Es sicher scheint wie ein peinlicher Moment für die Sprache.

ich die Ansicht des op teilen, dass Wiederholung ein bisschen ärgerlich, vor allem, wenn die Nicht-Aggregatfelder aufwendige Aussagen wie ifs und Funktionen und eine ganze Menge anderer Dinge enthalten. Es wäre schön, wenn es könnte einige Stenografie in der Gruppe durch Klausel sein - zumindest eine Spalte Alias. Unter Bezugnahme auf die Spalten von Nummer kann eine weitere Option sein, wenn auch eine, die wahrscheinlich ihre eigenen Probleme hat.

Es könnte eine Situation sein, dass Sie eine ID alle Reihen gruppierten zu extrahieren benötigt, und die Summe ihrer Mengen - zum Beispiel. In diesem Fall würden Sie das heißt Gruppe sie mit Namen und lassen ids nicht gruppiert. SQLite scheint diese Art und Weise zu arbeiten.

Da Gruppe von Ergebnis in einzelner Tupel für eine ganze Gruppe von Tupeln so andere nicht-Gruppe durch Attribute muß nur in Aggregatfunktion verwendet werden. Wenn u nicht Gruppe in ausgewählten durch Attribut hinzufügen, dann auf SQL Überhöhung, die von dieser Gruppe wählen zu sein, der Wert entscheiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top