Quelle est la différence d'un simple point de vue de la fonctionnalité de suppression des doublons
Outre le fait que, contrairement à DISTINCT
, GROUP BY
permet d'agréger des données par groupe (qui a été mentionné par de nombreuses autres réponses), la différence la plus importante à mon avis est le fait que les deux opérations "se produisent" à deux étapes très différentes dans l' ordre logique des opérations qui sont exécutées dans une SELECT
instruction .
Voici les opérations les plus importantes:
FROM
(y compris JOIN
, APPLY
, etc.)
WHERE
GROUP BY
(peut supprimer les doublons)
- Agrégations
HAVING
- Fonctions de fenêtre
SELECT
DISTINCT
(peut supprimer les doublons)
UNION
, INTERSECT
, EXCEPT
(Peut supprimer les doublons)
ORDER BY
OFFSET
LIMIT
Comme vous pouvez le voir, l'ordre logique de chaque opération influence ce qui peut être fait avec elle et comment elle influence les opérations suivantes. En particulier, le fait que l' GROUP BY
opération "se passe avant" l' SELECT
opération (la projection) signifie que:
- Cela ne dépend pas de la projection (ce qui peut être un avantage)
- Il ne peut utiliser aucune valeur de la projection (ce qui peut être un inconvénient)
1. Cela ne dépend pas de la projection
Un exemple où ne pas dépendre de la projection est utile est si vous voulez calculer des fonctions de fenêtre sur des valeurs distinctes:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Lorsqu'il est exécuté sur la base de données Sakila , cela donne:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
La même chose ne pouvait pas être obtenue avec DISTINCT
facilement:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Cette requête est "fausse" et donne quelque chose comme:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
Ce n'est pas ce que nous voulions. L' DISTINCT
opération "se produit après" la projection, nous ne pouvons donc plus supprimer les DISTINCT
classements car la fonction fenêtre a déjà été calculée et projetée. Pour l'utiliser DISTINCT
, nous devons imbriquer cette partie de la requête:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Note: Dans ce cas particulier, nous pourrions également utiliserDENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Il ne peut utiliser aucune valeur de la projection
L'un des inconvénients de SQL est parfois sa verbosité. Pour la même raison que ce que nous avons vu auparavant (à savoir l'ordre logique des opérations), nous ne pouvons pas "facilement" grouper par quelque chose que nous projetons.
Il s'agit d'un SQL non valide:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Ceci est valide (en répétant l'expression)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Ceci est également valable (imbriquer l'expression)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
J'ai écrit sur ce sujet plus en profondeur dans un article de blog