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:
- Es hängt nicht von der Projektion ab (was ein Vorteil sein kann)
- 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