2009-01-09 11 views
37

¿Por qué alguien usaría un grupo por medio de distinct cuando no hay agregaciones en la consulta?sql group por versus distinto

Además, alguien conoce el grupo en comparación con las distintas consideraciones de rendimiento en MySQL y SQL Server. Supongo que SQL Server tiene un mejor optimizador y que pueden estar cerca de su equivalente allí, pero en MySQL, espero que una ventaja de rendimiento significativo sea distinta.

Estoy interesado en dba answers.

EDIT:

posterior de Bill es interesante, pero no es aplicable. Déjame ser más específico ...

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

frente

select distinct a,b,c 
from table x 
+1

Esto está estrechamente relacionado con, pero no exactamente el mismo pregunta como, http://stackoverflow.com/questions/164319/is-there-any-difference-between-group-by-and-distinct –

+0

Probablemente porque no sabían de qué se trataban. Si estás seguro de que sabían de lo que se trataban, sospecharía que hay una diferencia en la forma en que los valores NULL son tratados entre los dos, sin embargo, no puedo pensar qué. –

+0

Creo que la respuesta es tan simple como: el escritor no sabía nada distinto (lo cual es sorprendente porque pensé que era profesional). – mson

Respuesta

18

Un poco (MUY poco) datos empíricos de MS SQL Server, en un par de tablas aleatorias de nuestro DB.

Para el patrón:

SELECT col1, col2 FROM table GROUP BY col1, col2 

y

SELECT DISTINCT col1, col2 FROM table 

Cuando no hay índice de cobertura para la consulta, en ambos sentidos produce el siguiente plan de consulta:

|--Sort(DISTINCT ORDER BY:([table].[col1] ASC, [table].[col2] ASC)) 
    |--Clustered Index Scan(OBJECT:([db].[dbo].[table].[IX_some_index])) 

y cuando hay fue un índice de cobertura, ambos producidos:

|--Stream Aggregate(GROUP BY:([table].[col1], [table].[col2])) 
    |--Index Scan(OBJECT:([db].[dbo].[table].[IX_some_index]), ORDERED FORWARD) 

por lo tanto, desde esa muestra muy pequeña SQL Server ciertamente trata a ambos de la misma manera.

+0

gracias por confirmar - supongo que los grandes vendedores han optimizado esto, pero también supongo que MySQL no lo ha hecho. – mson

2

Tanto generaría el mismo plan de consulta en MS SQL Server .... Si tiene MS SQL Server que sólo podría permitir a la real plan de ejecución para ver cuál es mejor para sus necesidades ...

favor, eche un vistazo a esos mensajes:

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

http://www.sqlmag.com/Article/ArticleID/24282/sql_server_24282.html

+0

usando group by en lugar de olores distintos como newb. hay mucha más sintaxis sin ganancia. también, no tiene métricas, solo rumores del blog de otra persona. – mson

28

GROUP BY grupos mapas de filas a una fila, por valor distintivo en columnas específicas, que ni siquiera necesariamente tienen que estar en la lista de selección.

SELECT b, c, d FROM table1 GROUP BY a; 

Esta consulta SQL es legal (corrección: sólo en MySQL, en realidad no es SQL estándar y no es compatible con otras marcas). MySQL lo acepta y confía en que sabe lo que está haciendo, seleccionando b, c y d de una manera inequívoca porque son functional dependencies de a.

Sin embargo, Microsoft SQL Server y otras marcas no permiten esta consulta, porque no puede determinar fácilmente las dependencias funcionales. editar: En cambio, el SQL estándar requiere que siga la regla de valor único, es decir, cada columna en la lista de selección debe ser nombrada en la cláusula GROUP BY o ser un argumento para una función establecida.

Considerando que DISTINCT siempre mira todas las columnas en la lista de selección, y solo esas columnas. Es un error común que DISTINCT le permite especificar las columnas:

SELECT DISTINCT(a), b, c FROM table1; 

A pesar de los paréntesis hacen DISTINCT mirada como llamada a la función, no lo es. Es una opción de consulta y un valor distinto en cualquiera de los tres campos de la lista de selección conducirá a una fila distinta en el resultado de la consulta. Una de las expresiones en esta lista de selección tiene paréntesis a su alrededor, pero esto no afectará el resultado.

+1

interesante pero irrelevante. está respondiendo una pregunta sobre cometer errores en las consultas. Además, no creo que sea un estándar ansi para aceptar una consulta como la que plantea. en todo caso, es un error en mysql; los otros proveedores principales no admiten esta 'característica' – mson

+0

Fuera del tema, pero la segunda consulta que Bill da (SELECT DISTINCT (a) ...) es perfectamente válida ANSI SQL-92. Los paréntesis son realmente irrelevantes; puede hacer SELECCIONAR a, (b), c FROM table1, y eso es válido. Es solo que, debido a que es el primer param, parece que la 'a' es un param de DISTINCT. – Cowan

+1

@mson: ¡Tienes razón! Lo busqué en mi "SQL-99 Complete, Really" y dice que la aplicación de la Regla de valor único es SQL estándar y un RDBMS que no lo hace cumplir (por ejemplo, MySQL) no se ajusta al estándar SQL. –

0

Si realmente busca valores distintos, los distintos hacen que el código fuente sea más legible (como si fuera parte de un procedimiento almacenado) Si estoy escribiendo consultas ad-hoc usualmente comenzaré con el grupo por, incluso si no tengo agregados porque a menudo los termino poniéndolos.

+0

hago lo mismo que tú, pero en la otra dirección. empiezo con select distinct y me muevo a group by si hay un motivo para hacerlo. No trato de optimizar todo, pero si puedo recordar algunas reglas generales sobre lo que es más rápido y más limpio, las sigo. grupo por es un poco desordenado-2 cláusulas – mson

3

En MySQL he encontrado que usar un GROUP BY a menudo es mejor en rendimiento que DISTINCT.

Al hacer una "EXPLAIN SELECT DISTINCT" se muestra "Using where; Using temporary" MySQL creará una tabla temporal.

vs un "EXPLAIN SELECT a, b, c de T1, T2, donde T2.A = t1.a GROUP BY un" sólo demuestra "Uso donde"

+0

siempre debe verificar la EXPLICACIÓN de su consulta en cuestión. Hoy recibí una consulta que decía "UTILIZAR temporalmente; UTILIZAR archivo ordenado" con agrupar pero solo "UTILIZAR temporalmente" con DISTINCT. por lo tanto, la variante DISTINCT fue 4 veces más rápida. (mysql 5.7) – staabm