Question

J'ai appris quelque chose de simple à propos de 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, existe-t-il quelque chose de différent dans la façon dont un moteur SQL traite la commande ou s'agit-il vraiment de la même chose?

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

EDIT: Ce n’est pas une question sur les agrégats. L'utilisation de GROUP BY avec des fonctions d'agrégat est comprise.

Était-ce utile?

La solution

La réponse de

MusiGenesis est fonctionnelle. le correct en ce qui concerne votre question comme indiqué; SQL Server est suffisamment intelligent pour se rendre compte que si vous utilisez " Regrouper par " et en n'utilisant aucune fonction d'agrégat, ce que vous entendez par "Distinct". - et génère donc un plan d'exécution comme si vous aviez simplement utilisé "Distinct".

Cependant, je pense qu'il est important de noter Hank La réponse de ainsi que le traitement désinvolte de & Group; Group By " et " Distinct " pourrait entraîner des pièges pernicieux si vous ne faites pas attention. Ce n’est pas tout à fait correct de dire que ceci n’est "pas une question sur les agrégats" vous vous interrogez sur la différence fonctionnelle entre deux mots clés de requête SQL, l'un d'entre eux est destiné à être utilisé avec des agrégats et l'autre non.

Un marteau peut parfois fonctionner pour visser une vis, mais si vous avez un tournevis à portée de main, pourquoi s'en soucier?

(pour les besoins de cette analogie, Hammer: Screwdriver :: GroupBy: Distinct et screw = > obtenir la liste des valeurs uniques dans une colonne du tableau )

Autres conseils

GROUP BY vous permet d'utiliser des fonctions d'agrégation, telles que AVG , MAX , MIN , SUM et COUNT . D'autre part, DISTINCT élimine simplement les doublons.

Par exemple, si vous avez plusieurs enregistrements d’achat et que vous souhaitez savoir combien a été dépensé par chaque service, vous pouvez effectuer les opérations suivantes:

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

Cela vous donnera une ligne par département, contenant le nom du département et la somme de toutes les valeurs montant de toutes les lignes de ce département.

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 groupe

Peut-être qu'il y a 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 Oracle):

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

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

Quelle est la différence avec le simple point de vue des fonctionnalités de suppression des doublons

Hormis le fait que, contrairement à DISTINCT , GROUP BY permet d'agréger des données par groupe (mentionnées dans de nombreuses autres réponses). , à mon avis, la différence la plus importante est le fait que les deux opérations "se produisent" à deux étapes très différentes dans ordre logique des opérations exécutées dans une instruction SELECT .

Voici les opérations les plus importantes:

  • FROM (y compris JOIN , APPLY , etc.)
  • O
  • GROUP BY (peut supprimer les doublons)
  • Agrégations
  • AYANT
  • Fonctions de la fenêtre
  • SELECT
  • DISTINCT (peut supprimer les doublons)
  • UNION , INTERSECT , EXCEPT (peut supprimer les doublons)
  • ORDER BY
  • OFFSET
  • LIMIT

Comme vous pouvez le constater, l’ordre logique de chaque opération influe sur ce qui peut en être fait et sur les opérations ultérieures. En particulier, le fait que l'opération GROUP BY "se produise avant" l'opération SELECT (la projection) signifie que:

  1. Cela ne dépend pas de la projection (ce qui peut être un avantage)
  2. 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

Si vous souhaitez calculer des fonctions de fenêtre sur des valeurs distinctes, voici un exemple où ne pas dépendre de la projection est utile:

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 , le résultat obtenu est le suivant:

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 "incorrecte". 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'opération DISTINCT "se produit après la projection . Par conséquent, nous ne pouvons plus supprimer les classifications DISTINCT car la fonction de fenêtre était déjà calculée et projetée. Pour utiliser DISTINCT , nous devrions 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 latérale: 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 précédemment (à savoir l'ordre logique des opérations), nous ne pouvons pas "facilement". groupe par quelque chose que nous projetons.

Ceci n'est pas valide SQL:

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 valide (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 de manière plus détaillée dans un article de blog

.

Je pense qu'il est possible que des différences subtiles soient observées dans leur exécution. J'ai vérifié les plans d'exécution pour deux requêtes équivalentes sur le plan fonctionnel 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: "HASH GROUP BY" " vs "HASH UNIQUE", mais les coûts estimés, etc. sont identiques. Je les ai ensuite exécutées avec le traçage activé et les comptages d'opération réels étaient les mêmes pour les deux (sauf que le second n'avait aucune lecture physique à cause de la mise en cache).

Mais je pense que, du fait 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é à des différences plus importantes.

Je pense que vous devriez préférer la syntaxe DISTINCT à cette fin. Ce n’est pas seulement une habitude, cela indique plus clairement le but de la requête.

Pour la requête que vous avez publiée, elles 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

J'ai lu tous les commentaires ci-dessus mais je n'ai vu personne indiquer la différence principale entre Group By et Distinct en dehors du bit d'agrégation.

Distinct renvoie toutes les lignes, puis les dédoublonne, tandis que Group By dédédupliquer les lignes au fur et à mesure qu'elles sont lues par l'algorithme une par une.

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 1 est un doublon d'un autre, la première requête renvoie 10 lignes, tandis que la deuxième requête en renvoie 9.

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

Si vous utilisez DISTINCT avec plusieurs colonnes, le jeu de résultats ne sera pas groupé comme il le fera avec GROUP BY et vous ne pourrez pas utiliser de fonctions d'agrégat avec DISTINCT.

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

GROUP BY a une signification très spécifique, distincte (heh) de la fonction DISTINCT.

GROUP BY permet de regrouper les résultats de la requête en utilisant l'expression choisie. Des fonctions d'agrégat peuvent ensuite être appliquées. Celles-ci agissent sur chaque groupe plutôt que sur l'ensemble du résultat.

Voici un exemple qui pourrait aider:

Étant donné un tableau ressemblant à ceci:

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

Cette requête:

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

Produira une sortie comme ceci:

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

Ce qui est évidemment très différent d’utiliser DISTINCT. Si vous souhaitez grouper vos résultats, utilisez GROUP BY, si vous souhaitez uniquement une liste unique d'une colonne spécifique, utilisez DISTINCT. Cela permettra à votre base de données d'optimiser la requête en fonction de vos besoins.

N'utilisez pas GROUP BY lorsque vous parlez de DISTINCT, même s’ils fonctionnent de la même manière. Je suppose que vous essayez d'économiser des millisecondes de requêtes, et je dois souligner que le temps passé par le développeur est beaucoup plus coûteux que le temps passé sur un ordinateur.

Si vous utilisez un GROUP BY sans aucune fonction d'agrégat, il sera traité en interne comme DISTINCT. Par conséquent, dans ce cas, il n'y a pas de différence entre GROUP BY et DISTINCT.

Toutefois, lorsque la clause DISTINCT vous est fournie, il est préférable de l'utiliser pour rechercher vos enregistrements uniques car l'objectif de GROUP BY est d'obtenir une agrégation.

group by est utilisé dans les opérations d'agrégation, comme lorsque vous souhaitez obtenir un nombre de Bs décomposé 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 semble que l’optimiseur de requêtes parvienne à optimiser la différence entre les exemples simplistes que j’ai exécutés. Je ne sais pas si vous pouvez compter sur cela dans toutes les situations, cependant.

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

Du point de vue du langage SQL, les deux constructions sont équivalentes et celle que vous choisissez fait partie de ces choix de "style de vie" que nous devons tous faire. Je pense qu'il est judicieux que DISTINCT soit plus explicite (et donc plus attentif à la personne qui héritera de votre code, etc.), mais cela ne signifie pas que la construction GROUP BY est un choix non valide.

Je pense que ce "GROUP BY est pour les agrégats" est le mauvais accent. Les gens doivent savoir que la fonction définie (MAX, MIN, COUNT, etc.) peut être omise afin de pouvoir comprendre l’intention du codeur quand elle le sera.

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

PS remarque que la position du mot clé DISTINCT dans la clause select peut produire des résultats différents, par ex. contraste:

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

Dans la perspective Teradata :

Du point de vue des résultats, peu importe si vous utilisez DISTINCT ou GROUP BY dans Teradata. L'ensemble de réponses sera le même.

Du point de vue des performances, ce n'est pas la même chose.

Pour comprendre l'impact sur les performances, vous devez savoir ce qui se passe sur Teradata lors de l'exécution d'une instruction avec DISTINCT ou GROUP BY.

Dans le cas de DISTINCT, les lignes sont immédiatement redistribuées sans aucune pré-agrégation, tandis que dans le cas de GROUP BY, une pré-agrégation est effectuée et les valeurs uniques ne sont ensuite redistribuées que sur les AMP.

Ne pensez pas maintenant que GROUP BY est toujours meilleur du point de vue des performances. Lorsque vous avez plusieurs 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 éliminer les doublons. Dans ce cas, il peut être préférable de redistribuer d’abord, c’est-à-dire utiliser l’instruction DISTINCT. L'instruction GROUP BY ne constitue probablement le meilleur choix que s'il existe plusieurs valeurs en double, car une fois que l'étape de déduplication a lieu, après la redistribution.

En résumé, DISTINCT vs. GROUP BY dans Teradata signifie:

GROUP BY - > pour beaucoup de doublons DISTINCT - > pas ou peu de doublons seulement. Parfois, lorsque vous utilisez DISTINCT, vous manquez d’espace de spool sur un AMP. La raison en est que la redistribution a lieu immédiatement et qu'un biais pourrait entraîner un manque d'espace pour les SAP.

Si cela se produit, GROUP BY a probablement de meilleures chances, car les doublons sont déjà supprimés dans un premier temps et que moins de données sont déplacées entre les AMP.

Vous ne le remarquez que 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

Ce qui afficherait la somme de toutes les transactions pour chaque personne.

Je sais que c'est un ancien post. Mais il se trouve que j'avais une requête qui utilisait group en retournant simplement des valeurs distinctes lorsque crapaud et oracle étaient utilisés, tout fonctionnait bien, ce qui signifie un temps de réponse satisfaisant. Lorsque nous avons migré d’Oracle 9i à 11g, le temps de réponse dans Toad était excellent, mais dans le rapport, il fallait environ 35 minutes pour terminer le rapport; lors de l’utilisation de la version précédente, cela prenait environ 5 minutes.

La solution consistait à modifier le groupe par et à utiliser DISTINCT. Le rapport est maintenant exécuté dans environ 30 secondes.

J'espère que cela est utile pour quelqu'un qui vit la même situation.

Comme je l’ai toujours compris, l’utilisation de distinct est identique à un regroupement de chaque champ sélectionné dans l’ordre dans lequel vous les avez sélectionnés.

i.e:

select distinct a, b, c from table;

est identique à:

select a, b, c from table group by a, b, c

L'efficacité fonctionnelle est totalement différente. Si vous souhaitez uniquement sélectionner la " valeur de retour " sauf dupliquer, utiliser distinct est mieux que group by. Parce que " groupe par " inclure (trier + enlever), "distincte" inclure (enlever)

Dans Hive (HQL), group by peut être beaucoup plus rapide que distinct, car le premier ne nécessite pas la comparaison de tous les champs de la table. Voir https://sqlperformance.com/2017 / 01 / t-sql-queries / surprises-suppositions-groupe par distinct .

Il n'y a pas de différence significative entre la clause group by et distinct, sauf l'utilisation de fonctions d'agrégat. Les deux peuvent être utilisés pour distinguer les valeurs, mais si, en termes de performances, grouper par est meilleur. Lorsqu'un mot clé distinct est utilisé, il utilise en interne une opération de tri qui peut être visualisée dans le plan d'exécution.

Essayez un exemple simple

Déclarer la table @tmpresult (   Id tinyint )

Insérer dans @tmpresult Sélectionnez 5 Union tout Sélectionnez 2 Union tout Sélectionnez 3 Union tout Sélectionnez 4

Sélectionnez distinct Id De @tmpresult

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top