¿Hay alguna diferencia entre GROUP BY y DISTINCT


Aprendí algo simple sobre SQL el otro día:

SELECT c FROM myTbl GROUP BY C

Tiene el mismo resultado que:

SELECT DISTINCT C FROM myTbl

De lo que tengo curiosidad, ¿hay algo diferente en la forma en que un motor SQL procesa el comando, o son realmente lo mismo?

Personalmente prefiero la sintaxis distinta, pero estoy seguro de que es más por costumbre que cualquier otra cosa.

EDITAR: Esta no es una pregunta sobre agregados. Se entiende el uso de GROUP BY con funciones agregadas.

Author: Brettski, 2008-10-03

24 answers

La respuesta de MusiGenesis es funcionalmente la correcta con respecto a su pregunta como se indica; el servidor SQL es lo suficientemente inteligente como para darse cuenta de que si está utilizando "Group By" y no utiliza ninguna función agregada, entonces lo que realmente significa es "Distinto" - y por lo tanto genera un plan de ejecución como si simplemente hubiera utilizado "Distinto"."

Sin embargo,creo que es importante tener en cuenta La respuesta de Hank también: el tratamiento arrogante de "Group By" y "Distinct" podría llevar a algún pernicioso te atrapará si no tienes cuidado. No es del todo correcto decir que esto "no es una pregunta sobre agregados" porque estás preguntando sobre la diferencia funcional entre dos palabras clave de consulta SQL, una de las cuales es destinada a ser utilizada con agregados y una de las cuales no lo es.

Un martillo puede funcionar para introducir un tornillo a veces , pero si tienes un destornillador a mano, ¿para qué molestarte?

(... a efectos de esta analogía, Hammer : Screwdriver :: GroupBy : Distinct y screw => get list of unique values in a table column)

 185
Author: Skeolan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-14 20:04:23

GROUP BY le permite usar funciones agregadas, como AVG, MAX, MIN, SUM, y COUNT. Other hand DISTINCT simplemente elimina duplicados.

Por ejemplo, si tienes un montón de registros de compras, y quieres saber cuánto gastó cada departamento, podrías hacer algo como:

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

Esto le dará una fila por departamento, que contiene el nombre del departamento y la suma de todos los valores amount en todas las filas para ese departamento.

 118
Author: Andru Luvisi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-31 11:25:43

No hay diferencia (al menos en SQL Server). Ambas consultas utilizan el mismo plan de ejecución.

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

Tal vez es una diferencia, si hay sub-consultas involucradas:

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

No hay diferencia (Estilo oráculo):

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

 38
Author: MusiGenesis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-05 00:28:33

Use DISTINCT si solo desea eliminar duplicados. Utilice GROUPY BY si desea aplicar operadores agregados(MAX, SUM, GROUP_CONCAT, ..., o una cláusula HAVING).

 29
Author: jkramer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-05 05:09:47

¿Cuál es la diferencia desde un simple punto de vista de la funcionalidad de eliminación de duplicados

Aparte del hecho de que a diferencia de DISTINCT, GROUP BY permite agregar datos por grupo (que ha sido mencionado por muchas otras respuestas), la diferencia más importante en mi opinión es el hecho de que las dos operaciones "suceden" en dos pasos muy diferentes en el orden lógico de las operaciones que se ejecutan en una instrucción SELECT .

Aquí están los más importantes operaciones:

  • FROM (incluidos JOIN, APPLY, etc.)
  • WHERE
  • GROUP BY (puede eliminar duplicados)
  • Agregaciones
  • HAVING
  • Funciones de ventana
  • SELECT
  • DISTINCT (puede eliminar duplicados)
  • UNION, INTERSECT, EXCEPT (puede eliminar duplicados)
  • ORDER BY
  • OFFSET
  • LIMIT

Como puede ver, el orden lógico de cada operación influye en lo que se puede hacer con él y cómo influye en las operaciones posteriores. En particular, el hecho de que la operación GROUP BY "sucede antes" la operación SELECT (la proyección) significa que:

  1. no depende de la proyección (que puede ser una ventaja)
  2. No puede usar ningún valor de la proyección (lo que puede ser una desventaja)

1. No depende de la proyección

Un ejemplo donde no depende de la la proyección es útil si desea calcular funciones de ventana en valores distintos:

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

Cuando se ejecuta contra la base de datos Sakila , esto produce:

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

Lo mismo no se podría lograr con DISTINCT fácilmente:

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

Esa consulta es "incorrecta" y produce algo como:

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

Esto no es lo que queríamos. La operación DISTINCT "sucede después de" la proyección, por lo que ya no podemos eliminar las clasificaciones DISTINCT porque la función de ventana era ya calculado y proyectado. Para usar DISTINCT, tendríamos que anidar esa parte de la consulta:

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

Nota al margen: En este caso particular, también podríamos usar DENSE_RANK()

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

2. No puede utilizar ningún valor de la proyección

Uno de los inconvenientes de SQL es su verbosidad a veces. Por la misma razón que lo que hemos visto antes (es decir, el orden lógico de las operaciones), no podemos "fácilmente" agrupar por algo que estamos proyectando.

Esto no es válido SQL:

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

Esto es válido (repitiendo la expresión)

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

Esto también es válido (anidando la expresión)

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

He escrito sobre este tema más en profundidad en una entrada de blog

 20
Author: Lukas Eder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-23 07:43:13

Espero que exista la posibilidad de diferencias sutiles en su ejecución. Comprobé los planes de ejecución de dos consultas funcionalmente equivalentes en estas líneas en 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 |
---------------------------------------------------------------------------

La operación intermedia es ligeramente diferente: "HASH GROUP BY" vs. "HASH UNIQUE", pero los costos estimados, etc. son idénticos. Luego ejecuté estos con tracing on y los recuentos de operaciones reales fueron los mismos para ambos (excepto que el segundo no tuvo que hacer ninguna lectura física debido a cache).

Pero creo que debido a que los nombres de las operaciones son diferentes, la ejecución seguiría rutas de código algo diferentes y eso abre la posibilidad de diferencias más significativas.

Creo que debería preferir la sintaxis DISTINTA para este propósito. No es solo un hábito, indica más claramente el propósito de la consulta.

 19
Author: Dave Costa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:51:01

Para la consulta que publicaste, son idénticas. Pero para otras consultas que pueden no ser ciertas.

Por ejemplo, no es lo mismo que:

SELECT C FROM myTbl GROUP BY C, D
 14
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:11:37

Tienen semántica diferente, incluso si tienen resultados equivalentes en sus datos particulares.

 11
Author: Hank Gay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:10:10

Si usa DISTINCT con varias columnas, el conjunto de resultados no se agrupará como lo hará con GROUP BY, y no puede usar funciones agregadas con DISTINCT.

 11
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:12:00

Leí todos los comentarios anteriores, pero no vi a nadie apuntando a la principal diferencia entre Group By y Distinct aparte del bit de agregación.

Distinct devuelve todas las filas y luego las des-duplica mientras que Agrupa Por des-desduplicar las filas a medida que el algoritmo las lee una por una.

Esto significa que pueden producir resultados diferentes!

Por ejemplo, los siguientes códigos generan diferentes resultados:

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

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

Si hay 10 nombres en la tabla donde 1 de los cuales es un duplicado de otro, entonces la primera consulta devuelve 10 filas, mientras que la segunda consulta devuelve 9 filas.

La razón es lo que dije anteriormente para que puedan comportarse de manera diferente!

 11
Author: The Light,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-17 16:04:57

GROUP BY tiene un significado muy específico que es distinto (jeh) de la función DISTINTA.

GROUP BY hace que los resultados de la consulta se agrupen utilizando la expresión elegida, luego se pueden aplicar funciones de agregado, y estas actuarán en cada grupo, en lugar de en todo el conjunto de resultados.

Aquí hay un ejemplo que podría ayudar:

Dada una tabla que se parece a esta:

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

Esta consulta:

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

Producirá una salida como esta:

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

Que es obviamente muy diferente de usar DISTINTO. Si desea agrupar sus resultados, use AGRUPAR POR, si solo desea una lista única de una columna específica, use DISTINTO. Esto le dará a su base de datos la oportunidad de optimizar la consulta para sus necesidades.

 5
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:20:31

Si está utilizando un GRUPO BY sin ninguna función agregada, internamente se tratará como DISTINTO, por lo que en este caso no hay diferencia entre GROUP BY y DISTINCT.

Pero cuando se le proporciona una cláusula DISTINTA, es mejor usarla para encontrar sus registros únicos porque el objetivo de GROUP BY es lograr la agregación.

 5
Author: Vikram Mahapatra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-25 14:29:54

Group by se usa en operaciones agregadas like como cuando desea obtener un recuento de Bs desglosado por columna C

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

Distinto es como suena get obtienes filas únicas.

En sql server 2005, parece que el optimizador de consultas es capaz de optimizar la diferencia en los ejemplos simplistas que ejecuté. Sin embargo, no sé si puedes contar con eso en todas las situaciones.

 4
Author: Danimal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:15:29

Por favor, no use GRUPO POR cuando se refiere a DISTINTO, incluso si sucede que funcionan de la misma manera. Estoy asumiendo que usted está tratando de reducir milisegundos de las consultas, y tengo que señalar que el tiempo de desarrollador es órdenes de magnitud más caro que el tiempo de la computadora.

 4
Author: Andy Lester,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:57:40

En esa consulta en particular no hay diferencia. Pero, por supuesto, si agrega cualquier columna agregada, entonces tendrá que usar group by.

 3
Author: Jeffrey L Whitledge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:12:44

Desde la perspectiva de 'SQL the language', las dos construcciones son equivalentes y la que elijas es una de esas elecciones de 'estilo de vida' que todos tenemos que hacer. Creo que hay un buen caso para que DISTINCT sea más explícito (y por lo tanto sea más considerado con la persona que heredará su código, etc.), pero eso no significa que el GRUPO POR construcción sea una opción no válida.

Creo que este 'GRUPO POR es para agregados' es el énfasis equivocado. Folk debe ser consciente de que la función set (MAX, MIN, COUNT, etc) se pueden omitir para que puedan entender la intención del codificador cuando lo es.

El optimizador ideal reconocerá construcciones SQL equivalentes y siempre elegirá el plan ideal en consecuencia. Para su motor SQL de la vida real de su elección, debe probar :)

PS tenga en cuenta que la posición de la palabra clave DISTINCT en la cláusula select puede producir resultados diferentes, por ejemplo, contraste:

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;
 2
Author: onedaywhen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-03 10:09:12

En la perspectiva de Teradata :

Desde el punto de vista del conjunto de resultados, no importa si utiliza DISTINCT o GROUP BY en Teradata. El conjunto de respuestas será el mismo.

Desde un punto de vista de rendimiento, no es lo mismo.

Para comprender qué afecta al rendimiento, debe saber qué sucede en Teradata al ejecutar una instrucción con DISTINCT o GROUP BY.

En el caso de DISTINCT, las filas se redistribuyen inmediatamente sin ninguna preagregación teniendo lugar, mientras que en el caso de GROUP BY, en un primer paso se realiza una preagregación y solo entonces se redistribuyen los valores únicos a través de los AMPs.

No pienses ahora que GROUP BY siempre es mejor desde el punto de vista del rendimiento. Cuando tienes muchos valores diferentes, el paso de preagregación de GROUP BY no es muy eficiente. Teradata tiene que ordenar los datos para eliminar duplicados. En este caso, puede ser mejor la redistribución primero, es decir, usar la declaración DISTINCT. Sólo si hay muchos valores duplicados, la instrucción GROUP BY es probablemente la mejor opción, ya que solo una vez que se lleva a cabo el paso de deduplicación, después de la redistribución.

En resumen, DISTINCT vs. GROUP BY in Teradata significa:

AGRUPAR POR - > para muchos duplicados DISTINCT - > no o solo unos pocos duplicados . A veces, cuando se utiliza DISTINCT, se queda sin espacio de carrete en un AMPLIFICADOR. La razón es que la redistribución tiene lugar inmediatamente, y sesgar podría causar que los amplificadores se queden sin espacio.

Si esto sucede, probablemente tenga una mejor oportunidad con GROUP BY, ya que los duplicados ya se eliminan en un primer paso y se mueven menos datos a través de los AMPs.

 2
Author: Ram Ghadiyaram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-23 03:24:07

Solo lo estás notando porque estás seleccionando una sola columna.

Intente seleccionar dos campos y vea lo que sucede.

Group By está pensado para ser utilizado de esta manera:

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

Que mostraría la suma de todas las transacciones para cada persona.

 1
Author: Chris Cudmore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 20:16:27

Sé que es un post antiguo. Pero sucede que tuve una consulta que utiliza grupo por sólo para devolver valores distintos cuando se utiliza esa consulta en informes de toad y oracle todo funcionó bien, me refiero a un buen tiempo de respuesta. Cuando migramos de Oracle 9i a 11g, el tiempo de respuesta en Toad fue excelente, pero en el reporte tardó unos 35 minutos en terminar el informe cuando se usó la versión anterior, tomó unos 5 minutos.

La solución fue cambiar el grupo por y usar DISTINTO y ahora el el informe se ejecuta en unos 30 segundos.

Espero que esto sea útil para alguien con la misma situación.

 1
Author: Gabriel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-29 16:06:26

La forma en que siempre lo entendí es que usar distinto es lo mismo que agrupar por cada campo que seleccionaste en el orden en que los seleccionaste.

Es decir:

select distinct a, b, c from table;

Es lo mismo que:

select a, b, c from table group by a, b, c
 0
Author: Zenshai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 21:05:41

Tuve esta pregunta antes, necesito agregar tres columnas de mi tabla de 4 millones de filas (las tres columnas en una nueva columna de una nueva tabla) pero solo las diferentes.

Así que ejecuté mi procedimiento almacenado que contiene esta consulta con el método 'group by' y tomó 32 minutos. Luego lo corrí de nuevo, pero con el método 'distinto' y me llevó 25 minutos.

Es el mismo resultado, pero fue un poco más rápido con el 2do método

 0
Author: Pedro Ivan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-19 11:31:12

La eficiencia funcional es totalmente diferente. Si desea seleccionar solo "valor devuelto" excepto duplicar uno, usar distinto es mejor que agrupar por. Debido a que" group by " include (ordenar + eliminar)," distinct " include ( eliminar)

 0
Author: Jun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-09 04:40:49

En Hive (HQL), agrupar por puede ser mucho más rápido que distinto, porque el primero no requiere comparar todos los campos de la tabla. Véase https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumptions-group-by-distinct.

 0
Author: John Jiang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-01 19:08:26

No hay diferencia significativa entre la cláusula group by y distinct excepto el uso de funciones agregadas. Ambos se pueden utilizar para distinguir los valores, pero si en el rendimiento punto de vista de grupo por es mejor. Cuando se utiliza la palabra clave distinct , internamente se utiliza la operación de ordenación que se puede ver en el plan de ejecución.

Prueba un ejemplo simple

Declare @ tmpresult table ( Id tinyint )

Insertar en @tmpresult Seleccionar 5 Union all Seleccione 2 Union all Seleccione 3 Union todo Seleccione 4

Seleccione distinto Id De @tmpresult

 -1
Author: Vinod Narwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-10 16:56:21