2012-08-25 11 views
10

Los siguientes dos consultas producen exactamente el mismo resultado:¿La cláusula HAVING es redundante?

select country, count(organization) as N 
from ismember 
group by country 
having N > 50; 

select * from (
    select country, count(organization) as N 
    from ismember 
    group by country) x 
where N > 50; 

Puede cada cláusula HAVING ser sustituido por un sub-consulta y una cláusula WHERE como esto? ¿O hay situaciones en las que una cláusula HAVING es absolutamente necesaria/más poderosa/más eficiente/lo que sea?

+3

Debe definir RDBMS a la pregunta, supongo. Su primera consulta no es válida en SQL Server 2008, porque no puede hacer una referencia en Tener en un alias en la selección. Solo en la parte OrderBy, debido al procesamiento de consultas lógicas. –

+0

Sospecho que MySQL? La primera consulta tampoco es válida en Oracle por el mismo motivo. – Ben

+0

@Ben Sí, acabo de agregar la etiqueta MySQL para aclarar. Gracias. – fredoverflow

Respuesta

9

Hay 2 preguntas aquí: La respuesta a la primera de las cuales es : El conjunto de resultados de una consulta HAVING -Laden es idéntica a la del conjunto de resultados de la misma consulta ejecutada como una subconsulta, decorado con una cláusula WHERE .

La segunda pregunta es sobre el rendimiento y la expresividad: aquí profundizamos en la implementación. En MySQL hay una delgada línea roja, donde el rendimiento comienza a desviarse: el momento en que el conjunto de resultados de la consulta interna ya no puede mantenerse en la memoria. En este caso, MySQL creará una representación en el disco de la consulta interna y luego usará el selector WHERE. Esto no sucederá, si se usa la cláusula HAVING, el grupo descalificado se eliminará del conjunto de resultados.

Esto implica que cuanto mayor sea la selectividad de la cláusula HAVING, mayor relevancia tendrá el rendimiento: Considere el conjunto de resultados de un millón de filas de la consulta interna, que se reduce por la cláusula HAVING a 5 filas - es muy es probable que el conjunto de resultados de la consulta interna no se guarde en la memoria, pero es muy probable que el conjunto de resultados final lo haga.

Editar

I tenía una vez: la consulta seleccionada los pocos valores atípicos de una tabla muy uniformemente distribuida (Número de piezas producidas en una máquina física en un taller por día). Investigué debido a la alta carga de IO.

Editar 2

Por favor, tenga en cuenta, que la caché de consultas es no utiliza para subconsultas - En mi humilde opinión un desarrollo lugar debería centrarse más en - por lo que el patrón de subconsulta no se beneficiarán del ser consulta interna un conjunto de resultados en caché

+0

+1 Es bueno tener en cuenta la cantidad de datos. –

0

En mi humilde opinión, utilizar la cláusula HAVING debería ser eficiente porque habría un pase adicional en la mesa de trabajo que contiene los resultados agrupados sobre los cuales se ejecuta el criterio de filtrado, en el segundo caso.

+0

Sub-consultas no ampliarse en tablas de trabajo. Las dos consultas (aunque con el problema del alias eliminado para otras plataformas) deben tratarse de manera idéntica. –

+0

@RobFarley Esto no es del todo cierto: si el conjunto de resultados excede un cierto tamaño, se materializará. –

+1

Ok. No en SQL Server u Oracle. Esos sistemas simplificarán la consulta. –

4

La cláusula HAVING es muy útil para evitar la complejidad adicional de las sub-consultas. Sin embargo, los dos son lógicamente equivalentes y cada cláusula HAVING se puede reescribir utilizando una subconsulta como la que tiene.

En caso de que tenga curiosidad, también podría escribir cada cláusula WHERE como una cláusula HAVING si está preparado para llevar GROUP BY al extremo.

+0

No estoy seguro de que su última línea sea verdadera ¿verdad? Supongamos que una tabla con una columna llamada 'number' y tres filas' VALUES (1), (1), (2) '¿Cómo se puede simular' SELECT number FROM FROM WHERE number = 1' con 'HAVING'? –

+0

Deberías agrupar el número. –

+0

Eso solo devolvería una fila. –

8

En Servidor SQL 2008 de dos consultas similares tienen exactamente el mismo plan de ejecución:

enter image description here

También he estudiado muchas consultas generadas por Entity Framework (con SS 2008) y hasta ahora nunca vi una consulta con una cláusula HAVING. Agrupamiento de consultas con una condición en un resultado agregado siempre se traduce en una consulta con una sub consulta. Confío en ADO.El equipo de red sabe con lo que están haciendo ...

+0

No confiaría en eso en absoluto. EF (y Linq-to-SQL) producen consultas notoriamente malas. –

+0

Acabo de intentar lo mismo :) + 1 eras más rápido :) –

+1

@RobFarley Sé que no pueden competir con consultas optimizadas y de forma manual, pero para las consultas automatizadas no son tan malas. Sin embargo, debes saber algo de lo que se debe hacer y lo que no se debe hacer al escribir linq. –

0

Sé que lo cambiaste de general a MySQL, pero me gustaría agregar aquí una nota (puede ser útil). Con una pequeña modificación que intentaron su consulta en SQL Server 2008.

Sólo por cualquier persona que quiera más detalle en ella, el executionplan de los dos consulta es aún exactamente el mismo en SQL Server 2008. Por lo tanto la optimizador procesando los dos comandos de la misma manera con el mismo rendimiento y estimaciones.

0

Lógicamente, sí, el resultado será el mismo al final. Pero el rendimiento puede diferir. La cláusula HAVING podría llevar al DB a cambiar un plan de ejecución diferente.

Una nota para los tipos anteriores (no se puede comentar directamente de alguna manera): el plan de ejecución no depende solo de su consulta. También puede ser ajustado por la base de datos en función de las estadísticas, como el tamaño de la tabla, etc. en tiempo de ejecución. Dicho esto para DB2 al menos ...

Cuestiones relacionadas