it-swarm.com.de

Gibt es einen Unterschied zwischen GROUP BY und DISTINCT?

Ich habe neulich etwas über SQL gelernt:

SELECT c FROM myTbl GROUP BY C

Hat das gleiche Ergebnis wie:

SELECT DISTINCT C FROM myTbl

Ich bin neugierig, gibt es etwas anderes in der Art, wie eine SQL-Engine den Befehl verarbeitet, oder sind sie wirklich dasselbe? 

Ich persönlich bevorzuge die eindeutige Syntax, aber ich bin sicher, dass es eher Gewohnheit ist als alles andere.

BEARBEITEN: Dies ist keine Frage zu Aggregaten. Die Verwendung von GROUP BY mit Aggregatfunktionen wird verstanden.

251
Brettski

MusiGenesis 'Antwort ist funktionell die richtige Antwort auf Ihre Frage wie angegeben; Der SQL Server ist intelligent genug, um zu erkennen, dass, wenn Sie "Group By" verwenden und keine Aggregatfunktionen verwenden, "Distinct" eigentlich "Distinct" bedeutet. Daher wird ein Ausführungsplan generiert, als hätten Sie einfach "Distinct" verwendet . "

Ich denke jedoch, dass es wichtig ist, die Reaktion von Hank zu beachten - die unbekümmerte Behandlung von "Group By" und "Distinct" könnte dazu führen, dass einige unheilvolle Tricks kommen, wenn Sie nicht aufpassen. Es ist nicht ganz richtig zu sagen, dass dies "keine Frage nach Aggregaten" ist, da Sie nach dem funktionalen Unterschied zwischen zwei SQL-Abfrageschlüsselwörtern gefragt werden, von denen eines ist, das mit Aggregaten verwendet werden soll, und eines davon ist nicht.

Ein Hammer kann manchmal arbeiten, um eine Schraube einzudrehen, aber wenn Sie einen Schraubenzieher zur Hand haben, warum dann die Mühe machen?

(Im Sinne dieser Analogie Hammer : Screwdriver :: GroupBy : Distinct und screw => get list of unique values in a table column)

202
Skeolan

Mit GROUP BY können Sie Aggregatfunktionen wie AVG, MAX, MIN, SUM und COUNT verwenden. Mit der anderen Hand DISTINCT werden nur Duplikate entfernt.

Wenn Sie beispielsweise eine Reihe von Kaufdatensätzen haben und wissen möchten, wie viel von den einzelnen Abteilungen ausgegeben wurde, können Sie Folgendes tun:

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

Dadurch erhalten Sie pro Abteilung eine Zeile, die den Abteilungsnamen und die Summe aller amount-Werte in allen Zeilen dieser Abteilung enthält.

125
Andru Luvisi

Es gibt keinen Unterschied (zumindest in SQL Server). Beide Abfragen verwenden denselben Ausführungsplan.

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

Vielleicht gibt es einen Unterschied , wenn es sich um Unterabfragen handelt:

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

Es gibt keinen Unterschied (Oracle-Stil):

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

41
MusiGenesis

Verwenden Sie DISTINCT, wenn Sie nur Duplikate entfernen möchten. Verwenden Sie GROUPY BY, wenn Sie Aggregatoperatoren anwenden möchten (MAX, SUM, GROUP_CONCAT, ... oder eine HAVING-Klausel).

30
jkramer

Was ist der Unterschied, wenn Sie nur die Funktion zum Entfernen von doppelten Dateien verwenden?

Abgesehen von der Tatsache, dass GROUP BY im Gegensatz zu DISTINCT die Aggregation von Daten pro Gruppe ermöglicht (was in vielen anderen Antworten erwähnt wurde), ist der wichtigste Unterschied meiner Meinung nach die Tatsache, dass die beiden Operationen zu zwei Zeitpunkten "passieren" verschiedene Schritte in der logischen Reihenfolge der Operationen, die in einer SELECT-Anweisung ausgeführt werden

Hier sind die wichtigsten Operationen:

  • FROM (einschließlich JOIN, APPLY usw.)
  • WHERE
  • GROUP BY(kann Duplikate entfernen)
  • Aggregationen
  • HAVING
  • Fensterfunktionen
  • SELECT
  • DISTINCT(kann Duplikate entfernen)
  • UNION, INTERSECT, EXCEPT(kann Duplikate entfernen)
  • ORDER BY
  • OFFSET
  • LIMIT

Wie Sie sehen, beeinflusst die logische Reihenfolge jeder Operation, was damit gemacht werden kann und wie sie nachfolgende Operationen beeinflusst. Insbesondere bedeutet die Tatsache, dass die GROUP BY-Operation "before" die SELECT-Operation (die Projektion) ist, Folgendes:

  1. Es kommt nicht auf die Projektion an (was von Vorteil sein kann)
  2. Es können keine Werte aus der Projektion verwendet werden (was nachteilig sein kann)

1. Es kommt nicht auf die Projektion an

Ein Beispiel, bei dem es nicht nützlich ist, von der Projektion abhängig zu sein, ist, wenn Sie Fensterfunktionen für verschiedene Werte berechnen möchten:

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

Wenn Sie gegen die Sakila-Datenbank laufen, erhalten Sie Folgendes:

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

Das Gleiche konnte mit DISTINCT nicht ohne weiteres erreicht werden:

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

Diese Abfrage ist "falsch" und ergibt so etwas wie:

rating   rn
------------
G        1
G        2
G        3
...
G        178
NC-17    179
NC-17    180
...

Das wollten wir nicht. Die DISTINCT-Operation "geschieht nach" der Projektion, sodass DISTINCT-Bewertungen nicht mehr entfernt werden können, da die Fensterfunktion bereits berechnet und projiziert wurde. Um DISTINCT verwenden zu können, müssen wir diesen Teil der Abfrage verschachteln:

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

Randnotiz: In diesem speziellen Fall könnten wir auch DENSE_RANK() verwenden.

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

2. Es können keine Werte aus der Projektion verwendet werden

Ein Nachteil von SQL ist manchmal die Ausführlichkeit. Aus dem gleichen Grund wie dem, was wir zuvor gesehen haben (nämlich der logischen Reihenfolge der Operationen), können wir nicht "leicht" nach etwas gruppieren, das wir projizieren.

Dies ist ungültige SQL:

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

Dies ist gültig (Wiederholung des Ausdrucks)

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

Dies gilt auch (Verschachtelung des Ausdrucks)

SELECT name
FROM (
  SELECT first_name || ' ' || last_name AS name
  FROM customer
) c
GROUP BY name

Ich habe zu diesem Thema ausführlicher in einem Blogbeitrag geschrieben

25
Lukas Eder

Ich gehe davon aus, dass es geringfügige Unterschiede bei der Ausführung gibt. Ich habe die Ausführungspläne für zwei funktional äquivalente Abfragen in Oracle 10g nach diesen Grundsätzen geprüft:

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 |
---------------------------------------------------------------------------

Die mittlere Operation ist etwas anders: "HASH GROUP BY" vs. "HASH UNIQUE", die geschätzten Kosten usw. sind jedoch identisch. Ich habe diese dann mit Nachverfolgung ausgeführt und die tatsächliche Anzahl der Vorgänge war für beide gleich (außer, dass der zweite Vorgang aufgrund von Zwischenspeicherung keine physischen Lesevorgänge durchführen musste).

Aber ich denke, da die Operationsnamen unterschiedlich sind, würde die Ausführung etwas unterschiedlichen Codepfaden folgen, was die Möglichkeit signifikanterer Unterschiede eröffnet.

Ich denke, Sie sollten für diesen Zweck die DISTINCT-Syntax vorziehen. Es ist nicht nur eine Gewohnheit, sondern gibt den Zweck der Abfrage klarer an.

19
Dave Costa

Für die von Ihnen gepostete Suchanfrage sind sie identisch. Aber für andere Abfragen trifft das möglicherweise nicht zu.

Zum Beispiel ist es nicht das Gleiche wie:

SELECT C FROM myTbl GROUP BY C, D
14
Joel Coehoorn

Ich habe alle obigen Kommentare gelesen, aber niemand sah den Hauptunterschied zwischen Group By und Distinct, abgesehen vom Aggregationsbit.

Distinct gibt alle Zeilen zurück und dekodiert sie, während Group By die Dekodierung der Zeilen vornimmt, wenn sie vom Algorithmus nacheinander gelesen werden.

Dies bedeutet, dass sie unterschiedliche Ergebnisse erzielen können!

Die folgenden Codes generieren beispielsweise unterschiedliche Ergebnisse:

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

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

Wenn die Tabelle 10 Namen enthält, von denen 1 ein Duplikat eines anderen ist, gibt die erste Abfrage 10 Zeilen zurück, während die zweite Abfrage 9 Zeilen zurückgibt.

Der Grund ist das, was ich oben gesagt habe, damit sie sich anders verhalten können!

12
The Light

Sie haben unterschiedliche Semantiken, auch wenn sie in Bezug auf Ihre Daten gleichwertige Ergebnisse haben.

11
Hank Gay

Wenn Sie DISTINCT mit mehreren Spalten verwenden, wird die Ergebnismenge nicht wie bei GROUP BY gruppiert und Sie können keine Aggregatfunktionen mit DISTINCT verwenden.

11
Bill the Lizard

GROUP BY hat eine sehr spezifische Bedeutung, die sich von der DISTINCT-Funktion unterscheidet.

GROUP BY bewirkt, dass die Abfrageergebnisse mit dem ausgewählten Ausdruck gruppiert werden. Aggregatfunktionen können dann angewendet werden, und diese wirken sich auf jede Gruppe und nicht auf das gesamte Resultset aus.

Hier ist ein Beispiel, das helfen könnte:

Angenommen, eine Tabelle sieht folgendermaßen aus:

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

Diese Abfrage:

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

Produziert folgende Ausgabe:

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

Was sich natürlich sehr von der Verwendung von DISTINCT unterscheidet. Wenn Sie Ihre Ergebnisse gruppieren möchten, verwenden Sie GROUP BY. Wenn Sie nur eine eindeutige Liste einer bestimmten Spalte wünschen, verwenden Sie DISTINCT. Dies gibt Ihrer Datenbank die Möglichkeit, die Abfrage für Ihre Anforderungen zu optimieren.

5
Dan

Bitte verwenden Sie GROUP BY nicht, wenn Sie DISTINCT meinen, auch wenn sie gleich funktionieren. Ich gehe davon aus, dass Sie versuchen, Millisekunden von Abfragen abzuwickeln, und ich muss darauf hinweisen, dass Entwicklerzeit um Größenordnungen teurer ist als Computerzeit.

5
Andy Lester

Wenn Sie eine GROUP BY ohne Aggregatfunktion verwenden, wird sie intern als DISTINCT behandelt. In diesem Fall besteht also kein Unterschied zwischen GROUP BY und DISTINCT.

Wenn Sie jedoch die DISTINCT-Klausel erhalten, sollten Sie sie besser zum Auffinden Ihrer eindeutigen Datensätze verwenden, da GROUP BY die Aggregation anstrebt.

5

group by wird in Aggregatvorgängen verwendet - beispielsweise, wenn Sie eine nach Spalte C aufgeschlüsselte Anzahl von Bs erhalten möchten

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

unterschiedlich ist es, wie es klingt - Sie erhalten eindeutige Reihen.

In SQL Server 2005 sieht es so aus, als könnte der Abfrageoptimierer die Unterschiede in den vereinfachten Beispielen, die ich ausgeführt habe, aus dem Weg räumen. Keine Ahnung, ob man sich in allen Situationen darauf verlassen kann.

4
Danimal

In dieser speziellen Abfrage gibt es keinen Unterschied. Wenn Sie jedoch Aggregatspalten hinzufügen, müssen Sie natürlich group by verwenden.

3

In Teradata-Perspektive

Aus der Sicht der Ergebnissätze spielt es keine Rolle, ob Sie in Teradata DISTINCT oder GROUP BY verwenden. Der Antwortsatz ist derselbe.

Aus Sicht der Leistung ist es nicht dasselbe.

Um zu verstehen, welche Auswirkungen auf die Leistung hat, müssen Sie wissen, was in Teradata passiert, wenn Sie eine Anweisung mit DISTINCT oder GROUP BY ausführen.

Bei DISTINCT werden die Zeilen sofort umverteilt, ohne dass eine Voraggregation stattfindet, während bei GROUP BY in einem ersten Schritt eine Voraggregation durchgeführt wird und erst dann die eindeutigen Werte auf die AMPs umverteilt werden.

Denken Sie jetzt nicht, dass GROUP BY aus Sicht der Leistung immer besser ist. Wenn Sie viele verschiedene Werte haben, ist der Voraggregationsschritt von GROUP BY nicht sehr effizient. Teradata muss die Daten sortieren, um Duplikate zu entfernen. In diesem Fall kann es besser sein, zuerst die Neuverteilung durchzuführen, d. H. Die Anweisung DISTINCT zu verwenden. Nur wenn es viele doppelte Werte gibt, ist die GROUP BY-Anweisung wahrscheinlich die bessere Wahl, da erst nach dem Umverteilen der Deduplizierungsschritt erfolgt. 

Kurz gesagt bedeutet DISTINCT vs. GROUP BY in Teradata:

GROUP BY -> für viele Duplikate DISTINCT -> keine oder nur wenige Duplikate. Bei Verwendung von DISTINCT ist der Spool-Speicherplatz auf einem AMP möglicherweise leer. Der Grund ist, dass die Umverteilung sofort stattfindet und durch das Verdrehen AMPs zu wenig Speicherplatz zur Verfügung steht. 

In diesem Fall haben Sie mit GROUP BY wahrscheinlich eine bessere Chance, da Duplikate bereits im ersten Schritt entfernt werden und weniger Daten über die AMPs verschoben werden.

2
Ram Ghadiyaram

Aus Sicht der "SQL the Language" sind die beiden Konstrukte gleichwertig. Welche Sie wählen, ist eine der 'Lifestyle'-Entscheidungen, die wir alle treffen müssen. Ich denke, es gibt einen guten Grund dafür, dass DISTINCT expliziter ist (und ist daher für die Person, die Ihren Code erbt usw.) rücksichtsvoller ist, aber das bedeutet nicht, dass das GROUP BY-Konstrukt eine ungültige Wahl ist. 

Ich denke, dass 'GROUP BY ist für Aggregate' der falsche Schwerpunkt ist. Folk sollte sich bewusst sein, dass die eingestellte Funktion (MAX, MIN, COUNT usw.) weggelassen werden kann, um die Absicht des Codierers zu verstehen, wenn dies der Fall ist.

Der ideale Optimierer erkennt gleichwertige SQL-Konstrukte und wählt immer den idealen Plan aus. Für Ihre echte SQL-Engine der Wahl müssen Sie testen :)

Beachten Sie, dass die Position des DISTINCT-Schlüsselworts in der Select-Klausel zu unterschiedlichen Ergebnissen führen kann, z. Kontrast: 

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;
2
onedaywhen

Ich weiß, dass es ein alter Beitrag ist. Aber es kam vor, dass ich eine Abfrage hatte, bei der group verwendet wurde, um bei der Verwendung dieser Abfrage in Kröten- und Oracle-Berichten eindeutige Werte zurückzugeben. Alles hat gut funktioniert. Ich meine, eine gute Antwortzeit. Als wir von Oracle 9i auf 11g migrierten, war die Antwortzeit in Toad hervorragend, aber in der Berichterstattung dauerte es etwa 35 Minuten, bis der Bericht fertig war, als die vorherige Version verwendet wurde. Es dauerte etwa 5 Minuten.

Die Lösung bestand darin, die Gruppe durch DISTINCT zu ändern und sie zu verwenden. Jetzt läuft der Bericht in etwa 30 Sekunden.

Ich hoffe, das ist nützlich für jemanden mit derselben Situation.

1
Gabriel

Sie merken das nur, weil Sie eine einzelne Spalte auswählen.

Versuchen Sie, zwei Felder auszuwählen und sehen Sie, was passiert.

Group By soll folgendermaßen verwendet werden:

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

Welches würde die Summe aller Transaktionen für jede Person anzeigen.

1
Chris Cudmore

Funktionale Effizienz ist völlig anders. Wenn Sie nur "Rückgabewert" auswählen möchten, mit Ausnahme eines doppelten, ist die Verwendung von different besser als gruppieren nach. Da "gruppieren nach" einschließen (sortieren + entfernen), "verschieden" einschließen (entfernen) 

0
Jun

Manchmal liefern sie möglicherweise die gleichen Ergebnisse, sind jedoch dazu gedacht, in einem anderen Sinn/Fall verwendet zu werden. Der Hauptunterschied liegt in der Syntax.

Beachten Sie das folgende Beispiel genau. DISTINCT dient zum Herausfiltern der doppelten Wertemenge. (6, cs, 9.1) und (1, cs, 5.5) sind zwei verschiedene Mengen. Also zeigt DISTINCT beide Zeilen an, während GROUP BY Branch nur einen Satz anzeigt.

 SELECT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT DISTINCT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT * FROM student GROUP BY Branch;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    2 | mech   |  6.3 |
+------+--------+------+
4 rows in set (0.001 sec)

Manchmal können die Ergebnisse, die mit der GROUP BY -Klausel erzielt werden können, nicht mit DISTINCT erzielt werden, ohne dass zusätzliche Klauseln oder Bedingungen verwendet werden. Zum Beispiel in obigem Fall.

Um das gleiche Ergebnis wie DISTINCT zu erhalten, müssen Sie alle Spaltennamen in der GROUP BY -Klausel wie unten übergeben. Sehen Sie also den syntaktischen Unterschied. Sie müssen alle Spaltennamen kennen, um in diesem Fall die GROUP BY -Klausel verwenden zu können.

SELECT * FROM student GROUP BY Id, Branch, CGPA;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    1 | cs     |  5.5 |
|    2 | mech   |  6.3 |
|    3 | civil  |  7.2 |
|    4 | eee    |  8.2 |
|    6 | cs     |  9.1 |
+------+--------+------+

Ich habe auch bemerkt, dass GROUP BY die Ergebnisse standardmäßig in aufsteigender Reihenfolge anzeigt, was DISTINCT nicht tut. Da bin ich mir aber nicht sicher. Dies kann je nach Anbieter unterschiedlich sein.

Quelle: https://dbjpanda.me/dbms/languages/sql/sql-syntax-with-examples#group-by

0
SkyRar

Im Allgemeinen können wir DISTINCT verwenden, um die Duplikate für bestimmte Spalten in der Tabelle zu entfernen.

Im Fall von 'GROUP BY' können wir die Aggregationsfunktionen wie AVG, MAX, MIN, SUM und COUNT auf eine bestimmte Spalte anwenden und die abrufen Spaltenname und Aggregationsfunktion ergeben sich für dieselbe Spalte.

Beispiel:

select  specialColumn,sum(specialColumn) from yourTableName group by specialColumn;
0
Lova Chittumuri

In Hive (HQL) kann group by weitaus schneller als eindeutig sein, da beim ersteren nicht alle Felder in der Tabelle verglichen werden müssen. Siehe https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumptions-group-by-distinct .

0
John Jiang

Ich hatte diese Frage vorher, ich muss drei Spalten aus meiner 4 Millionen-Zeilen-Tabelle (die drei Spalten in eine neue Spalte einer neuen Tabelle) anfügen, aber nur die anderen. 

Also habe ich meine gespeicherte Prozedur ausgeführt, die diese Abfrage mit der Methode 'group by' enthält, und es dauerte 32 Minuten. Dann habe ich es erneut laufen lassen, aber mit "eindeutiger" Methode und es dauerte 25 Minuten. 

Es ist das gleiche Ergebnis, aber mit der 2. Methode war es etwas schneller

0
Pedro Ivan

Ich verstand es immer so, dass die Verwendung von unterscheidend der Gruppierung nach jedem Feld entspricht, das Sie in der von Ihnen ausgewählten Reihenfolge ausgewählt haben. 

das heißt:

select distinct a, b, c from table;

ist das gleiche wie:

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