Qual é a diferença de um mero ponto de vista da funcionalidade de remoção duplicada
Além do fato de que DISTINCT
, diferentemente , GROUP BY
permite agregar dados por grupo (que já foi mencionado por muitas outras respostas), a diferença mais importante na minha opinião é o fato de as duas operações "acontecerem" em duas etapas muito diferentes na ordem lógica. de operações que são executadas em uma SELECT
instrução .
Aqui estão as operações mais importantes:
FROM
(incluindo JOIN
, APPLY
etc.)
WHERE
GROUP BY
(pode remover duplicatas)
- Agregações
HAVING
- Funções da janela
SELECT
DISTINCT
(pode remover duplicatas)
UNION
, INTERSECT
, EXCEPT
(Pode remover duplicados)
ORDER BY
OFFSET
LIMIT
Como você pode ver, a ordem lógica de cada operação influencia o que pode ser feito com ela e como ela influencia as operações subseqüentes. Em particular, o fato de a GROUP BY
operação "acontecer antes" da SELECT
operação (a projeção) significa que:
- Não depende da projeção (o que pode ser uma vantagem)
- Ele não pode usar nenhum valor da projeção (o que pode ser uma desvantagem)
1. Não depende da projeção
Um exemplo em que não é útil depender da projeção é se você deseja calcular as funções da janela em valores distintos:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Quando executado no banco de dados Sakila , isso gera:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
O mesmo não poderia ser alcançado com DISTINCT
facilidade:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Essa consulta está "errada" e produz algo como:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
Não é isso que queríamos. A DISTINCT
operação "acontece depois" da projeção, portanto não podemos mais remover DISTINCT
classificações porque a função da janela já foi calculada e projetada. Para usar DISTINCT
, teríamos que aninhar essa parte da consulta:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Nota lateral: Nesse caso em particular, também poderíamos usarDENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Ele não pode usar nenhum valor da projeção
Uma das desvantagens do SQL é sua verbosidade às vezes. Pelo mesmo motivo que vimos antes (a ordem lógica das operações), não podemos "facilmente" agrupar por algo que estamos projetando.
Este é SQL inválido:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Isso é válido (repetindo a expressão)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Isso também é válido (aninhando a expressão)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
Eu escrevi sobre esse tópico com mais profundidade em uma postagem no blog