493 Stimmen

Gibt es einen Unterschied zwischen GROUP BY und DISTINCT

Neulich habe ich etwas Einfaches über SQL gelernt:

SELECT c FROM myTbl GROUP BY C

Hat das gleiche Ergebnis wie:

SELECT DISTINCT C FROM myTbl

Ich bin neugierig, ob es einen Unterschied in der Art und Weise gibt, wie eine SQL-Engine den Befehl verarbeitet, oder ob es sich wirklich um dasselbe handelt.

Ich persönlich bevorzuge die eindeutige Syntax, aber ich bin mir sicher, dass das eher aus Gewohnheit so ist.

EDIT: Es handelt sich nicht um eine Frage über Aggregate. Die Verwendung von GROUP BY mit Aggregatfunktionen verstanden wird.

338voto

Skeolan Punkte 4038

MusiGenesis Der SQL Server ist schlau genug, um zu erkennen, dass Sie "Gruppieren nach" und keine Aggregatfunktionen verwenden, wenn Sie eigentlich "Unterscheiden" meinen - und daher wird ein Ausführungsplan erstellt, als ob Sie einfach "Unterscheiden" verwendet hätten.

Ich halte es jedoch für wichtig zu beachten Hank Der leichtfertige Umgang mit "Gruppieren nach" und "Unterscheiden" kann zu einigen bösen Überraschungen führen, wenn man nicht vorsichtig ist. Es ist nicht ganz korrekt zu sagen, dass dies "keine Frage über Aggregate" ist, denn Sie fragen nach dem funktionalen Unterschied zwischen zwei SQL-Abfrage-Schlüsselwörtern, von denen eines lautet für die Verwendung mit Aggregaten bestimmt und eine davon ist nicht.

Manchmal kann man eine Schraube auch mit einem Hammer eintreiben, aber wenn man einen Schraubenzieher zur Hand hat, warum sollte man sich die Mühe machen?

(für die Zwecke dieser Analogie, Hammer : Screwdriver :: GroupBy : Distinct y screw => get list of unique values in a table column )

189voto

Andru Luvisi Punkte 23151

GROUP BY können Sie Aggregatfunktionen verwenden, wie AVG , MAX , MIN , SUM et COUNT . Auf der anderen Seite DISTINCT entfernt lediglich die Duplikate.

Wenn Sie z. B. eine Reihe von Kaufdatensätzen haben und wissen möchten, wie viel von jeder Abteilung ausgegeben wurde, könnten Sie etwas wie folgt tun:

SELECT department, SUM(amount) FROM purchases GROUP BY department

So erhalten Sie eine Zeile pro Abteilung, die den Abteilungsnamen und die Summe aller amount Werte in allen Zeilen für diese Abteilung.

111voto

Lukas Eder Punkte 194234

Was ist der Unterschied aus der Sicht der reinen Duplikatentfernung?

Abgesehen von der Tatsache, dass im Gegensatz zu DISTINCT , GROUP BY ermöglicht die Aggregation von Daten pro Gruppe (was bereits in vielen anderen Antworten erwähnt wurde), ist der wichtigste Unterschied meiner Meinung nach die Tatsache, dass die beiden Vorgänge in zwei sehr unterschiedlichen Phasen des Prozesses "passieren". logische Reihenfolge der Operationen, die in einem SELECT Anweisung .

Hier sind die wichtigsten Vorgänge:

  • FROM (einschließlich JOIN , APPLY , usw.)
  • WHERE
  • GROUP BY (kann Duplikate entfernen)
  • Aggregate
  • HAVING
  • Fenster-Funktionen
  • SELECT
  • DISTINCT (kann Duplikate entfernen)
  • UNION , INTERSECT , EXCEPT (kann Duplikate entfernen)
  • ORDER BY
  • OFFSET
  • LIMIT

Wie Sie sehen können, beeinflusst die logische Reihenfolge jeder Operation, was mit ihr gemacht werden kann und wie sie die nachfolgenden Operationen beeinflusst. Insbesondere die Tatsache, dass die GROUP BY Betrieb "passiert vorher" die SELECT Operation (die Projektion) bedeutet, dass:

  1. Es hängt nicht von der Projektion ab (was ein Vorteil sein kann)
  2. Sie kann keine Werte aus der Projektion verwenden (was ein Nachteil sein kann)

1. Es hängt nicht von der Projektion ab

Ein Beispiel, bei dem die Unabhängigkeit von der Projektion nützlich ist, ist die Berechnung von Fensterfunktionen für bestimmte Werte:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating

Bei der Ausführung gegen den Sakila-Datenbank ergibt sich daraus:

rating   rn
-----------
G        1
NC-17    2
PG       3
PG-13    4
R        5

Das Gleiche konnte nicht erreicht werden mit DISTINCT leicht:

SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film

Diese Abfrage ist "falsch" und ergibt etwas wie:

rating   rn
------------
G        1
G        2
G        3
...
G        178
NC-17    179
NC-17    180
...

Das ist nicht das, was wir wollten. Die DISTINCT Betrieb "passiert danach" die Projektion, so dass wir nicht mehr entfernen können DISTINCT Bewertungen, da die Fensterfunktion bereits berechnet und projiziert wurde. Für die Verwendung DISTINCT müssten wir diesen Teil der Abfrage verschachteln:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
  SELECT DISTINCT rating FROM film
) f

Randnotiz: In diesem speziellen Fall könnten wir auch Folgendes verwenden DENSE_RANK()

SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film

2. Sie kann keine Werte aus der Projektion verwenden

Einer der Nachteile von SQL ist, dass es zuweilen sehr langatmig ist. Aus demselben Grund, den wir bereits gesehen haben (nämlich die logische Reihenfolge der Operationen), können wir nicht "einfach" nach etwas gruppieren, das wir projizieren.

Dies ist ungültiges SQL:

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name

Dies ist gültig (Wiederholung des Ausdrucks)

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name

Dies ist auch gültig (Verschachtelung des Ausdrucks)

SELECT name
FROM (
  SELECT first_name || ' ' || last_name AS name
  FROM customer
) c
GROUP BY name

Ich habe über dieses Thema in einem Blogbeitrag ausführlicher geschrieben

52voto

MusiGenesis Punkte 72729

Es gibt keinen Unterschied (zumindest in SQL Server). Beide Abfragen verwenden denselben Ausführungsplan.

http://sqlmag.com/database-performance-tuning/distinct-vs-group

Vielleicht gibt es est einen Unterschied, wenn es sich um Unterabfragen handelt:

http://blog.sqlauthority.com/2007/03/29/sql-server-difference-between-distinct-and-group-by-distinct-vs-group-by/

Es gibt keinen Unterschied (im Oracle-Stil):

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212

42voto

jkramer Punkte 15030

Utilice DISTINCT wenn Sie nur Duplikate entfernen wollen. Verwenden Sie GROUPY BY wenn Sie Aggregatoperatoren anwenden wollen ( MAX , SUM , GROUP_CONCAT , ..., oder ein HAVING Klausel).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X