Pregunta

El otro día aprendí algo simple sobre SQL:

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 de SQL procesa el comando o son realmente lo mismo?

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

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

¿Fue útil?

Solución

MusiGenesis 'la respuesta es funcional la correcta con respecto a su pregunta como se indica; SQL Server es lo suficientemente inteligente como para darse cuenta de que si está usando " Agrupar por " y al no utilizar ninguna función agregada, lo que realmente quiere decir es " Distinct " - y, por lo tanto, genera un plan de ejecución como si simplemente hubiera usado " Distinct. "

Sin embargo, creo que es importante tener en cuenta Hank La respuesta de también es un tratamiento complejo de " Group By " y " Distinct " podría llevar a algunos errores perniciosos en la línea si no tienes cuidado. No es del todo correcto decir que esto no es una pregunta sobre agregados " porque está preguntando acerca de la diferencia funcional entre dos palabras clave de consulta SQL, una de las cuales es destinada a usarse con agregados y una de las cuales no lo es.

Un martillo puede trabajar para atornillar en un tornillo a veces, pero si tienes un destornillador a mano, ¿para qué molestarse?

(para los fines de esta analogía, Hammer: Screwdriver :: GroupBy: Distinct y screw = > obtiene la lista de valores únicos en una columna de la tabla )

Otros consejos

GROUP BY le permite usar funciones agregadas, como AVG , MAX , MIN , SUM y COUNT . Por otro lado, DISTINCT simplemente elimina los duplicados.

Por ejemplo, si tiene un montón de registros de compra, y quiere saber cuánto gastó cada departamento, podría 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 de monto en todas las filas de ese departamento.

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 hay una diferencia, si hay subconsultas involucradas:

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

No hay diferencia (estilo Oracle):

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

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

¿Cuál es la diferencia de un mero punto de vista de la funcionalidad de eliminación duplicada?

Aparte del hecho de que, a diferencia de DISTINCT , GROUP BY permite agregar datos por grupo (lo cual 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 orden lógico de las operaciones que se ejecutan en una declaración SELECT .

Estas son las operaciones más importantes:

  • FROM (incluido JOIN , APPLY , etc.)
  • WHERE
  • GROUP BY (puede eliminar duplicados)
  • Agregaciones
  • HAVING
  • funciones de la 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 ella y en cómo influye en las operaciones subsiguientes. En particular, el hecho de que la operación GROUP BY " ocurra antes de " 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 en el que no depender de la proyección es útil es si desea calcular las funciones de la ventana en valores distintos:

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

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

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

No se pudo lograr lo mismo 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 " ocurre después de " la proyección, por lo que ya no podemos eliminar las calificaciones de DISTINCT porque la función de ventana ya estaba calculada y proyectada. Para utilizar DISTINCT , deberíamos 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 utilizar DENSE_RANK ()

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

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

Uno de los inconvenientes de SQL es su verbosidad a veces. Por el mismo motivo que hemos visto anteriormente (es decir, el orden lógico de las operaciones), no podemos " fácilmente " Grupo por algo que estamos proyectando.

Esto no es SQL válido:

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

Esto es válido (repetir 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 más a fondo sobre este tema en una publicación de blog

Espero que exista la posibilidad de diferencias sutiles en su ejecución. Verifiqué los planes de ejecución para 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 los ejecuté con el rastreo activado y los recuentos de operaciones reales fueron los mismos para ambos (excepto que el segundo no tuvo que hacer ninguna lectura física debido al almacenamiento en caché).

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 DISTINCT para este propósito. No es solo un hábito, sino que indica más claramente el propósito de la consulta.

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

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

Distinct devuelve todas las filas y luego las desduplica, mientras que Group By elimina la deduplicación de las filas a medida que las lee el algoritmo una por una.

¡Esto significa que pueden producir resultados diferentes!

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

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 ellos es un duplicado de otro, 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!

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.

Tienen diferentes semánticas, incluso si tienen resultados equivalentes en sus datos particulares.

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

GRUPO POR hace que los resultados de la consulta se agrupen utilizando la expresión elegida, luego se pueden aplicar funciones agregadas, que actuarán en cada grupo, en lugar de en el conjunto de resultados completo.

Aquí hay un ejemplo que podría ayudar:

Dada una tabla que se ve así:

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

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

Por favor, no use GROUP BY cuando quiere decir DISTINCT, incluso si funcionan de la misma manera. Supongo que está intentando eliminar milisegundos de las consultas, y debo señalar que el tiempo del desarrollador es mucho más caro que el tiempo de la computadora.

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

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

Agrupar por se usa en operaciones agregadas, como cuando se quiere obtener una cuenta de Bs desglosada por la columna C

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

distinto es lo que suena: obtienes filas únicas.

En el servidor SQL 2005, parece que el optimizador de consultas puede optimizar la diferencia en los ejemplos simplistas que ejecuté. No sé si puedes contar con eso en todas las situaciones, sin embargo.

En esa consulta particular no hay diferencia. Pero, por supuesto, si agrega columnas agregadas, tendrá que usar agrupar por.

Desde la perspectiva de 'SQL the language', las dos construcciones son equivalentes y la que elija 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, es más considerado para la persona que heredará su código, etc.) pero eso no significa que la construcción GROUP BY no sea una opción válida.

Creo que este 'GRUPO POR es para agregados' es el énfasis equivocado. La gente debe saber que la función de ajuste (MAX, MIN, COUNT, etc.) se puede omitir para que puedan entender la intención del codificador cuando sea.

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

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

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

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 el punto de vista del rendimiento, no es lo mismo.

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

En el caso de DISTINCT, las filas se redistribuyen inmediatamente sin que tenga lugar ninguna preagregación, 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 AMP.

No piense ahora que GROUP BY siempre es mejor desde el punto de vista del rendimiento. Cuando tiene muchos valores diferentes, el paso de preagregación de GROUP BY no es muy eficiente. Teradata tiene que ordenar los datos para eliminar los duplicados. En este caso, puede ser mejor para la redistribución primero, es decir, usar la instrucción DISTINCT. Solo 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 en Teradata significa:

GRUPO POR - > para muchos duplicados DISTINTO - > No o solo algunos duplicados. A veces, cuando usa DISTINCT, se queda sin espacio de spool en un AMP. La razón es que la redistribución tiene lugar de inmediato, y el sesgo podría hacer que los AMP se queden sin espacio.

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

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

Intente seleccionar dos campos y vea qué sucede.

Agrupar por está destinado a utilizarse de esta forma:

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

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

Sé que es un post viejo. Pero sucede que tuve una consulta que usaba el grupo solo para devolver valores distintos al usar esa consulta en informes de sapo y oráculo 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 informe tardamos unos 35 minutos en finalizar el informe. Cuando usamos la versión anterior, demoramos unos 5 minutos.

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

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

La forma en que lo entendí siempre es que usar distintas es lo mismo que agrupar por cada campo que seleccionó en el orden en que las seleccionó.

es decir:

select distinct a, b, c from table;

es lo mismo que:

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

La eficiencia funcional es totalmente diferente. Si desea seleccionar solo " valor de retorno " excepto duplicar uno, usar distinto es mejor que agrupar por. Porque " agrupar por " incluir (ordenar y eliminar), " distinto " incluir (eliminar)

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

No hay una diferencia significativa entre el grupo por y la cláusula distinta, excepto el uso de funciones agregadas. Ambos se pueden usar para distinguir los valores, pero si en el punto de vista de rendimiento el grupo es mejor. Cuando se usa una palabra clave distinta, internamente usó una operación de clasificación que puede verse en el plan de ejecución.

Prueba el ejemplo simple

Declare @tmpresult table (   Id tinyint )

Insertar en @tmpresult Seleccione 5 Unión de todos Seleccione 2 Unión de todos Seleccione 3 Unión de todos Seleccione 4

Seleccionar distinto Carné de identidad Desde @tmpresult

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top