Qual è la differenza da un semplice punto di vista della funzionalità di rimozione duplicata
A parte il fatto che a differenza DISTINCT
, GROUP BY
consente di aggregare dati per gruppo (che è stato menzionato da molte altre risposte), la differenza più importante secondo me è il fatto che le due operazioni "avvengono" in due fasi molto diverse nell'ordine logico delle operazioni eseguite in una SELECT
dichiarazione .
Ecco le operazioni più importanti:
FROM
(tra cui JOIN
, APPLY
, etc.)
WHERE
GROUP BY
(può rimuovere i duplicati)
- aggregazioni
HAVING
- Funzioni della finestra
SELECT
DISTINCT
(può rimuovere i duplicati)
UNION
, INTERSECT
, EXCEPT
(Può rimuovere i duplicati)
ORDER BY
OFFSET
LIMIT
Come puoi vedere, l'ordine logico di ogni operazione influenza ciò che può essere fatto con essa e come influenza le operazioni successive. In particolare, il fatto che l' GROUP BY
operazione "avviene prima" l' SELECT
operazione (sporgenza) significa che:
- Non dipende dalla proiezione (che può essere un vantaggio)
- Non può utilizzare alcun valore dalla proiezione (che può essere uno svantaggio)
1. Non dipende dalla proiezione
Un esempio in cui non dipende dalla proiezione è utile se si desidera calcolare le funzioni della finestra su valori distinti:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Quando eseguito contro il database Sakila , questo produce:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
Lo stesso non si può ottenere DISTINCT
facilmente con :
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Quella query è "sbagliata" e produce qualcosa di simile:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
Questo non è quello che volevamo. L' DISTINCT
operazione "avviene dopo" la proiezione, quindi non possiamo più rimuovere le DISTINCT
classificazioni perché la funzione finestra era già calcolata e proiettata. Per poterlo utilizzare DISTINCT
, dovremmo nidificare quella parte della query:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Nota a margine: in questo caso particolare, potremmo anche usareDENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Non può utilizzare alcun valore dalla proiezione
Uno degli svantaggi di SQL è la sua verbosità a volte. Per lo stesso motivo di ciò che abbiamo visto prima (vale a dire l'ordine logico delle operazioni), non possiamo "facilmente" raggruppare per qualcosa che stiamo proiettando.
Questo è SQL non valido:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Questo è valido (ripetendo l'espressione)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Anche questo è valido (annidando l'espressione)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
Ho scritto più approfonditamente su questo argomento in un post sul blog