Y a-t-il une différence entre groupe par et DISTINCT

j'ai appris quelque chose de simple sur SQL l'autre jour:

SELECT c FROM myTbl GROUP BY C

a le même résultat que:

SELECT DISTINCT C FROM myTbl

ce que je suis curieux de savoir, est-ce qu'il y a quelque chose de différent dans la façon dont un moteur SQL traite la commande, ou sont-ils vraiment la même chose?

personnellement, je préfère la syntaxe distincte, mais je suis sûr que c'est plus par habitude qu'autre chose.

EDIT: ce n'est pas une question de Aggregate. L'utilisation de GROUP BY avec des fonctions agrégées est comprise.

239
demandé sur Brettski 2008-10-03 00:09:06

24 réponses

MusiGenesis ' la réponse est fonctionnellement correcte en ce qui concerne votre question comme indiqué; le serveur SQL est assez intelligent pour réaliser que si vous utilisez "Group By" et n'utilisez pas de fonctions agrégées, alors ce que vous voulez réellement dire est "Distinct" - et donc il génère un plan d'exécution comme si vous aviez simplement utilisé "Distinct"."

cependant, je pense qu'il est important de noter Hank ' S réponse ainsi - un traitement cavalier de "groupe par" et "Distinct" pourrait mener à un gotcha pernicieux en bas de la ligne si vous n'êtes pas prudent. Il n'est pas tout à fait correct de dire que ce n'est "pas une question sur les agrégats" parce que vous posez des questions sur la différence fonctionnelle entre deux mots-clés de requête SQL, dont l'un est destiné à être utilisé avec les agrégats et l'autre ne l'est pas.

un marteau peut fonctionner pour conduire dans une vis parfois , mais si vous avez un tournevis à portée de main, pourquoi s'embêter?

(... aux fins de la présente analogie, Hammer : Screwdriver :: GroupBy : Distinct et screw => get list of unique values in a table column )

185
répondu Skeolan 2018-02-14 20:04:23

GROUP BY vous permet d'utiliser des fonctions agrégées, comme AVG , MAX , MIN , SUM , et COUNT . D'autre part DISTINCT supprime simplement les doublons.

Par exemple, si vous avez un tas de dossiers d'achat, et vous voulez savoir combien a été dépensé par chaque département, vous pourriez faire quelque chose comme:

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

Cela vous donnera une ligne par département, contenant le nom du département et de la somme de toutes les valeurs amount dans toutes les rangées pour ce ministère.

118
répondu Andru Luvisi 2014-07-31 11:25:43

il n'y a pas de différence (au moins dans SQL Server). Les deux requêtes utilisent le même plan d'exécution.

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

peut-être qu'il y a est une différence, s'il y a des sous-requêtes impliquées:

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

Il n'y a pas de différence (style d'Oracle):

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

38
répondu MusiGenesis 2013-04-05 00:28:33

utilisez DISTINCT si vous voulez simplement supprimer les doublons. Utilisez GROUPY BY si vous voulez appliquer des opérateurs agrégés ( MAX , SUM , GROUP_CONCAT , ..., ou une clause HAVING ).

29
répondu jkramer 2012-09-05 05:09:47

Quelle est la différence d'une simple suppression des doublons de la fonctionnalité de point de vue

outre le fait que contrairement à DISTINCT , GROUP BY permet d'agréger des données par groupe (ce 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 le ordre logique des opérations qui sont exécutées dans un SELECT déclaration .

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 et comment il influence les opérations ultérieures. En particulier, le fait que le GROUP BY opération "se produit avant " le SELECT opération (la projection) signifie que:

  1. Il ne dépend pas de la projection (qui peut être un avantage)
  2. il ne peut utiliser aucune valeur de la projection (ce qui peut être un inconvénient)

1. Il ne dépend pas de l' projection

un exemple où ne pas dépendre de la projection est utile est si vous voulez calculer les fonctions de fenêtre sur des valeurs distinctes:

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

lorsqu'on utilise la base de données Sakila , on obtient:

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

la même chose ne pourrait pas être réalisée avec DISTINCT facilement:

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

cette requête est "erronée" 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. Le DISTINCT opération "se produit après " la projection, de sorte que nous ne pouvons plus Supprimer DISTINCT évaluations parce que la fonction de fenêtre était déjà calculé et projeté. Pour utiliser DISTINCT , il faudrait faire un nid dans cette partie de la requête:

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

Side-note: dans ce cas particulier, nous pourrions également utiliser DENSE_RANK()

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

2. Il ne peut utiliser aucune valeur de la projection

un des inconvénients de SQL est sa verbosité parfois. 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.

ceci est un SQL invalide:

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

ceci est valable (en répétant l'expression)

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

(nidification de 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 billet de blog

20
répondu Lukas Eder 2017-08-23 07:43:13

Je m'attends à ce qu'il y ait la possibilité de différences subtiles dans leur exécution. J'ai vérifié les plans d'exécution pour deux requêtes fonctionnellement équivalentes selon ces lignes dans Oracle 10g:

core> select sta from zip group by sta;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH GROUP BY     |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

core> select distinct sta from zip;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH UNIQUE       |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

l'opération du milieu est légèrement différente:" groupe de hachage par "vs." unique de hachage", mais les coûts estimés etc. sont identiques. Je les ai ensuite exécutés avec traçage et le nombre réel d'opérations était le même pour les deux (sauf que le second n'avait pas à faire toutes les lectures physiques en raison de la mise en cache).

mais je pense que parce que les noms d'opération sont différents, l'exécution suivrait des chemins de code quelque peu différents et cela ouvre la possibilité de différences plus significatives.

je pense que vous devriez préférer la syntaxe distincte à cet effet. Ce n'est pas seulement l'habitude, cela indique plus clairement le but de la requête.

19
répondu Dave Costa 2008-10-02 20:51:01

pour la requête que vous avez postée, ils sont identiques. Mais pour d'autres requêtes qui peuvent ne pas être vraies.

par exemple, ce n'est pas la même chose que:

SELECT C FROM myTbl GROUP BY C, D
14
répondu Joel Coehoorn 2008-10-02 20:11:37

ils ont une sémantique différente, même s'ils ont des résultats équivalents sur vos données particulières.

11
répondu Hank Gay 2008-10-02 20:10:10

si vous utilisez DISTINCT avec plusieurs colonnes, le résultat ne sera pas groupé comme il le sera avec GROUP BY, et vous ne pouvez pas utiliser des fonctions agrégées avec DISTINCT.

11
répondu Bill the Lizard 2008-10-02 20:12:00

j'ai lu tous les commentaires ci-dessus, mais je n'ai vu personne pointer la différence principale entre Groupe par et Distinct en dehors du bit d'agrégation.

renvoie toutes les lignes, puis les dés-duplique, tandis que Group By dés-désduplie les lignes, car elles sont lues par l'algorithme un par un.

Cela signifie qu'ils peuvent produire des résultats différents!

par exemple, les codes ci-dessous génèrent des résultats différents:

SELECT distinct ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable

 SELECT ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable
GROUP BY Name

S'il y a 10 noms dans la table dont l'un est un duplicata d'un autre, alors la première requête renvoie 10 lignes tandis que la seconde renvoie 9 lignes.

la raison est ce que j'ai dit ci-dessus pour qu'ils puissent se comporter différemment!

11
répondu The Light 2012-05-17 16:04:57

groupe BY a un sens très spécifique qui est distinct (heh) de la fonction distincte.

groupe par causes les résultats de la requête à être groupés en utilisant l'expression choisie, les fonctions agrégées peuvent alors être appliquées, et ceux-ci agiront sur chaque groupe, plutôt que l'ensemble des résultats.

voici un exemple qui pourrait aider:

donné un tableau qui ressemble à ceci:

name
------
barry
dave
bill
dave
dave
barry
john

cette requête:

SELECT name, count(*) AS count FROM table GROUP BY name;

va produire la sortie comme ceci:

name    count
-------------
barry   2
dave    3
bill    1
john    1

, ce qui est évidemment très différent de L'utilisation de DISTINCT. Si vous voulez grouper vos résultats, utilisez GROUP BY, si vous voulez juste une liste unique d'une colonne spécifique, utilisez DISTINCT. Cela donnera à votre base de données d'une optimisation de la requête pour vos besoins.

5
répondu Dan 2008-10-02 20:20:31

si vous utilisez un groupe par sans n'importe quelle fonction agrégée alors à l'intérieur il sera traité comme DISTINCT, ainsi dans ce cas il n'y a aucune différence entre groupe par et DISTINCT.

mais lorsqu'on vous fournit une clause distincte, mieux vaut l'utiliser pour trouver vos documents uniques parce que L'objectif de GROUP BY est d'atteindre l'agrégation.

5
répondu Vikram Mahapatra 2015-03-25 14:29:54

group by est utilisé dans les opérations agrégées -- comme quand vous voulez obtenir un compte de Bs ventilé par colonne c

select C, count(B) from myTbl group by C

distinct est ce que cela ressemble -- vous obtenez des lignes uniques.

Dans sql server 2005, il ressemble à l'optimiseur de requête est en mesure d'optimiser loin la différence dans le simpliste des exemples que j'ai couru. Je ne sais pas si tu peux compter sur ça dans toutes les situations.

4
répondu Danimal 2008-10-02 20:15:29

S'il vous plaît n'utilisez pas Groupe par quand vous voulez dire DISTINCT, même si elles se trouvent à travailler le même. Je suppose que vous essayez de couper millisecondes de requêtes, et je dois souligner que le temps de développement est des ordres de grandeur plus cher que le temps d'ordinateur.

4
répondu Andy Lester 2008-10-02 20:57:40

Dans cette requête, il n'y a pas de différence. Mais, bien sûr, si vous ajoutez des colonnes agrégées, vous devrez utiliser group by.

3
répondu Jeffrey L Whitledge 2008-10-02 20:12:44

du point de vue du langage, les deux concepts sont équivalents et celui que vous choisissez est l'un de ces choix de "style de vie" que nous devons tous faire. Je pense qu'il y a de bonnes raisons pour que DISTINCT soit plus explicite (et est donc plus attentionné à la personne qui héritera de votre code, etc) mais cela ne signifie pas que le groupe par construction est un choix invalide.

je pense que "GROUP BY is for aggregates" est la mauvaise emphase. Folk doivent être conscients que la fonction set (MAX, MIN, COUNT, etc) peut être omise pour qu'ils puissent comprendre l'intention du codeur quand il est.

l'optimiseur idéal reconnaîtra les constructions SQL équivalentes et choisira toujours le plan idéal en conséquence. Pour votre vie réelle du moteur SQL de choix, vous devez tester :)

PS notez la position du mot clé DISTINCT dans la clause select peut produire des résultats différents par exemple le contraste:

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;
2
répondu onedaywhen 2008-10-03 10:09:12

Dans Teradata point de vue :

du point de vue du jeu de résultats, peu importe que vous utilisiez DISTINCT ou GROUP BY in Teradata. La réponse sera la même.

du point de vue de la performance, ce n'est pas la même chose.

pour comprendre ce qui affecte la performance, vous devez savoir ce qui se passe sur Teradata lors de l'exécution d'une instruction avec DISTINCT ou GROUP BY.

In dans le cas de DISTINCT, les lignes sont redistribuées immédiatement sans aucune préagrégation, tandis que dans le cas de GROUP BY, dans un premier temps une préagrégation est effectuée et ce n'est qu'alors que les valeurs uniques sont redistribuées à travers les Sap.

ne pensez pas maintenant que GROUP BY est toujours meilleur du point de vue de la performance. Lorsque vous avez beaucoup de valeurs différentes, L'étape de préagrégation de GROUP BY n'est pas très efficace. Teradata doit trier les données pour supprimer les doublons. Dans ce cas, il peut être préférable de procéder d'abord à la redistribution, c'est-à-dire d'utiliser L'énoncé DISTINCT. Seulement s'il y a beaucoup de valeurs dupliquées, le GROUP BY statement est probablement le meilleur choix car seulement une fois que l'étape de duduplication a lieu, après la redistribution.

en bref, DISTINCT vs. GROUP BY in Teradata signifie:

GROUPE -> pour de nombreux doublons DISTINCT - > pas ou quelques copies seulement . Parfois, quand vous utilisez DISTINCT, vous êtes à court de bobine de l'espace sur un ampli. La raison en est que la redistribution a lieu immédiatement, et l'inclinaison pourrait provoquer des Amplis à manquer d'espace.

si cela se produit, vous avez probablement une meilleure chance avec GROUP BY, car les doublons sont déjà supprimés dans une première étape, et moins de données sont déplacées à travers les Sap.

2
répondu Ram Ghadiyaram 2018-06-23 03:24:07

vous le remarquez seulement parce que vous sélectionnez une seule colonne.

essayez de sélectionner deux champs et voyez ce qui se passe.

Group By est destiné à être utilisé comme ceci:

SELECT name, SUM(transaction) FROM myTbl GROUP BY name

qui indiquerait la somme de toutes les transactions pour chaque personne.

1
répondu Chris Cudmore 2008-10-02 20:16:27

je sais que c'est un vieux post. Mais il se trouve que j'ai eu une requête qui a utilisé group by juste pour retourner des valeurs distinctes en utilisant cette requête dans les rapports toad et oracle tout a bien fonctionné, je veux dire un bon temps de réponse. Lorsque nous avons migré D'Oracle 9i à 11g le temps de réponse dans Toad était excellent mais dans le rapport il a fallu environ 35 minutes pour terminer le rapport en utilisant la version précédente il a fallu environ 5 minutes.

la solution était de changer le groupe et l'utilisation DISTINCTES et maintenant, le rapport s'exécute en environ 30 secondes.

j'espère que cela est utile pour quelqu'un avec la même situation.

1
répondu Gabriel 2016-01-29 16:06:26

La façon dont j'ai toujours entendu que l'utilisation de distinct est le même que le regroupement par chaque champ que vous avez sélectionné dans l'ordre de leur sélection.

I. e:

select distinct a, b, c from table;

est le même que:

select a, b, c from table group by a, b, c
0
répondu Zenshai 2008-10-02 21:05:41

j'ai eu cette question avant, je dois ajouter trois colonnes de mon tableau de 4 millions de lignes (les trois colonnes dans une nouvelle colonne d'un nouveau tableau) mais seulement les différentes.

alors j'ai lancé ma procédure stockée qui contient cette requête avec la méthode 'group by' et cela a pris 32 minutes. Puis je l'ai refait, mais avec une méthode "distincte" et ça a pris 25 minutes.

c'est le même résultat, mais c'était un peu plus rapide avec la 2ème méthode

0
répondu Pedro Ivan 2017-01-19 11:31:12

l'efficacité fonctionnelle est totalement différente. Si vous souhaitez sélectionner seulement "valeur de retour" sauf dupliquer un, utiliser distinct est mieux que group by. Parce que "group by" comprend (tri + suppression ), "distinct" comprend (suppression )

0
répondu Jun 2018-01-09 04:40:49

Dans la Ruche (HQL), le groupe peut être de manière plus rapide que distinctes, parce que le premier n'a pas besoin de comparer tous les champs de la table. Voir https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumptions-group-by-distinct .

0
répondu John Jiang 2018-07-01 19:08:26

il n'y a pas de différence significative entre la clause groupe par groupe et la clause distincte, sauf en ce qui concerne l'utilisation des fonctions agrégées. Les deux peuvent être utilisés pour distinguer les valeurs, mais si dans la performance point de vue groupe par est meilleur. Lorsque le mot-clé distinct est utilisé , en interne il a utilisé l'opération de tri qui peut être vue dans le plan d'exécution.

Essayez de simple exemple

Declare @tmresult table ( Id de type tinyint )

insérer dans @tmpresult Sélectionnez 5 L'Union de tous Sélectionner 2 L'Union de tous Sélectionnez 3 L'Union de tous Sélectionner 4

sélectionner distinct ID De @tmpresult

-1
répondu Vinod Narwal 2015-02-10 16:56:21