¿Cuál es la diferencia entre tener y dónde?


261

Debo buscar en Google de manera incorrecta o estoy teniendo un momento estúpido en el tiempo.

¿Cuál es la diferencia entre HAVINGy WHEREen una SQL SELECTdeclaración?

EDITAR: He marcado la respuesta de Steven como la correcta ya que contenía la información clave en el enlace:

Cuando GROUP BYno se usa, se HAVINGcomporta como una WHEREcláusula

La situación que había visto WHEREen el no tenía GROUP BYy es donde comenzó mi confusión. Por supuesto, hasta que sepa esto, no puede especificarlo en la pregunta.


44
La línea que cita no es la clave en absoluto. El bit clave, como señaló wcm , es que HAVINGes un filtro de agregación posterior, mientras que WHEREes un filtro de agregación previa.
Nick Chammas el

este enlace me ayudó a entenderlo mejor que todos los comentarios a continuación, pensé que alguien podría obtener ayuda con este codeproject.com/Articles/25258/…
Durairaj

Respuestas:


94

HAVING especifica una condición de búsqueda para un grupo o una función agregada utilizada en la instrucción SELECT.

Fuente


369

TENIENDO: se utiliza para verificar las condiciones después de la agregación.
DONDE: se utiliza para verificar las condiciones antes de que se realice la agregación.

Este código:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

Le da una tabla de todas las ciudades en MA y el número de direcciones en cada ciudad.

Este código:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

Le da una tabla de ciudades en MA con más de 5 direcciones y el número de direcciones en cada ciudad.


77
Esta debería ser la respuesta aceptada. La distinción entre "tener" y "dónde" deja esto inmediatamente claro.
Paul

27

La diferencia número uno para mí: si HAVINGse eliminó del lenguaje SQL, la vida continuaría más o menos como antes. Ciertamente, las consultas de una minoría tendrían que reescribirse usando una tabla derivada, CTE, etc., pero como resultado podrían ser más fáciles de entender y mantener. Tal vez el código del optimizador de los proveedores deba reescribirse para tener esto en cuenta, una vez más, una oportunidad de mejora dentro de la industria.

Ahora considere por un momento eliminar WHEREdel lenguaje. Esta vez, la mayoría de las consultas existentes deberían reescribirse sin una construcción alternativa obvia. Los codificadores tendrían que ser creativos, por ejemplo, la unión interna a una tabla que se sabe que contiene exactamente una fila (por ejemplo, DUALen Oracle) usando la ONcláusula para simular la WHEREcláusula anterior . Tales construcciones serían inventadas; sería obvio que faltaba algo en el lenguaje y la situación sería peor como resultado.

TL; DR podríamos perder HAVINGmañana y las cosas no serían peores, posiblemente mejores, pero no se puede decir lo mismo WHERE.


De las respuestas aquí, parece que muchas personas no se dan cuenta de que una HAVINGcláusula puede usarse sin una GROUP BYcláusula. En este caso, la HAVINGcláusula se aplica a toda la expresión de la tabla y requiere que solo aparezcan constantes en la SELECTcláusula. Típicamente la HAVINGcláusula involucrará agregados.

Esto es más útil de lo que parece. Por ejemplo, considere esta consulta para probar si la namecolumna es única para todos los valores en T:

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

Solo hay dos resultados posibles: si la HAVINGcláusula es verdadera, el resultado será una sola fila que contenga el valor 1; de lo contrario, el resultado será el conjunto vacío.


¿Sería equivalente a "SELECT COUNT (DISTINCT name) = COUNT (name) FROM T"?
MSpreij

@MSpreij No sé si eso funciona para usted, pero no funciona en SQL Server 2005, pero el primero sí lo hace
Joe

22

La cláusula HAVING se agregó a SQL porque la palabra clave WHERE no se pudo usar con funciones agregadas.

Mira este enlace de w3schools para más información

Sintaxis:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

Una consulta como esta:

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

... puede reescribirse usando una tabla derivada (y omitiendo HAVING) como esta:

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;

3
Has perdido un poco el punto: HAVINGse agregó porque las tablas derivadas no se habían agregado al lenguaje y hasta que se SQL no estaba relacionalmente completo y una vez que inevitablemente se HAVINGvolvieron redundantes.
día

21

La diferencia entre los dos está en la relación con la cláusula GROUP BY:

  • DONDE viene antes de GROUP BY; SQL evalúa la cláusula WHERE antes de agrupar registros.

  • HABER viene después de GROUP BY; SQL evalúa HAVING después de que agrupa los registros.

seleccione diagrama de declaración

Referencias


Dado que GROUP BY y HAVING son opcionales, el diagrama muestra ambos casos, solo siga las flechas.
Paul Sweatte

Ejemplo de consulta de mi respuesta a esta pregunta: SELECT 1 AS result FROM T HAVING...- en su diagrama no puedo acceder HAVINGsin pasar, GROUP BYpero mi consulta perfectamente válida y útil no tiene GROUP BY. Punto menor: no tiene la opción de incluir valores literales en la SELECTcláusula.
cuando el

@onedaywhen Ya que conoces el GROUP BY implícito, ¿por qué no lo mencionaste? ¿Sabes si este comportamiento es lo que esperas o no?
Paul Sweatte

Creo que me estás citando fuera de contexto. La pregunta era sobre la aparente desviación de mySQL del Estándar, todos excepto el último párrafo de mi respuesta describe el comportamiento del Estándar, y el último alude a "la cláusula GROUP BY implícita mencionada en otras respuestas ". ¿Está diciendo que su diagrama tiene la intención de describir (todos) el comportamiento implícito? ¿No sería más útil apegarse solo al código que necesita escribir para obtener el comportamiento deseado?
cuando el

... No sé a qué comportamiento te refieres en el segundo enlace. El resultado deseado es que arregle el diagrama para mostrar la ruta válida (explícita) que mencioné. Piénselo: el diagrama cubre una consulta completa, pero la pregunta solo está interesada en la WHERE->HAVINGparte, por lo que creo que merece mucha atención al detalle. Si cree que mi respuesta es incorrecta, edítela o publique una corrección sugerida en los comentarios.
cuando el

12

HAVINGse usa cuando usa un agregado como GROUP BY.

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;

8

WHERE se aplica como una limitación en el conjunto devuelto por SQL; utiliza las operaciones e índices de conjuntos integrados de SQL y, por lo tanto, es la forma más rápida de filtrar conjuntos de resultados. Siempre use DONDE cuando sea posible.

Tener es necesario para algunos filtros agregados. Filtra la consulta DESPUÉS de que sql haya recuperado, ensamblado y ordenado los resultados. Por lo tanto, es mucho más lento que DONDE y debe evitarse, excepto en aquellas situaciones que lo requieran.

SQL Server le permitirá usar HAVING incluso cuando WHERE sería mucho más rápido. No lo hagas


La compatibilidad con tablas derivadas en el lenguaje SQL significa que su afirmación "TENER ES NECESARIO para algunos filtros agregados" es falsa.
día

1
Ese es un buen punto. En los tres años transcurridos desde que escribí esta respuesta, ciertamente he migrado hacia el uso de tablas derivadas donde anteriormente hubiera usado HAVING. No he pensado en la cuestión de si TENER todavía tiene algunos casos de uso que tengan sentido. Tampoco sé si una tabla derivada funcionará universalmente mejor que HAVING.
davidcl

7

La cláusula WHERE no funciona para funciones agregadas
significa: no debe usar como esta bonificación: nombre de la tabla

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

AQUÍ En lugar de usar la cláusula WHERE, debe usar HAVING ..

sin usar la cláusula GROUP BY, la cláusula HAVING simplemente funciona como la cláusula WHERE

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  

4

Diferencia b / w WHEREy HAVINGcláusula:

La principal diferencia entre WHEREy HAVINGcláusula es, WHEREse usa para operaciones de fila y HAVINGse usa para operaciones de columna.

¿Por qué necesitamos una HAVINGcláusula?

Como sabemos, las funciones agregadas solo se pueden realizar en columnas, por lo que no podemos usar funciones agregadas en la WHEREcláusula. Por lo tanto, utilizamos funciones agregadas en la HAVINGcláusula.


2

Cuando GROUP BYno se usa, las cláusulas WHEREy HAVINGson esencialmente equivalentes.

Sin embargo, cuando GROUP BYse usa:

  • La WHEREcláusula se usa para filtrar registros de un resultado. El filtrado se produce antes de realizar cualquier agrupación.
  • La HAVINGcláusula se utiliza para filtrar valores de un grupo (es decir, para verificar las condiciones después de que se haya realizado la agregación en grupos).

Recurso desde aquí


teniendo y donde no son esencialmente equivalentes. dará error durante la ejecución. no es válido en la cláusula HAVING porque no está contenido ni en una función agregada ni en la cláusula GROUP BY.
Nagendra Kumar

2

Una forma de pensarlo es que la cláusula have es un filtro adicional a la cláusula where.

Se utiliza una cláusula WHERE para filtrar registros de un resultado. El filtro se produce antes de realizar agrupaciones. Una cláusula HAVING se usa para filtrar valores de un grupo


1

En una consulta agregada, (Cualquier consulta donde se utiliza una función agregada) Predica en una cláusula where antes de que se genere el conjunto de resultados intermedios agregados,

Los predicados en una cláusula Have se aplican al conjunto de resultados agregado DESPUÉS de que se haya generado. Es por eso que las condiciones de predicado en los valores agregados deben colocarse en la cláusula Have, no en la cláusula Where, y por qué puede usar alias definidos en la cláusula Select en una cláusula Have, pero no en una cláusula Where.


1

Tuve un problema y descubrí otra diferencia entre WHEREy HAVING. No actúa de la misma manera en columnas indexadas.

WHERE my_indexed_row = 123 mostrará filas y realizará automáticamente un "ORDER ASC" en otras filas indexadas.

HAVING my_indexed_row = 123 muestra todo, desde la fila "insertada" más antigua hasta la más nueva, sin ordenar.


¿Cómo sabe que esta es una diferencia definida entre los dos, en lugar de un accidente de implementación del servidor SQL particular que estaba utilizando?
JdeBP

Lo acabo de probar en MariaDB. Supongo que fue el servidor SQL que estaba usando hace 8 años el que produjo resultados diferentes.
Simmoniz

0

A partir de aquí .

el estándar SQL requiere que HAVING solo haga referencia a columnas en la cláusula GROUP BY o columnas utilizadas en funciones agregadas

a diferencia de la cláusula WHERE que se aplica a las filas de la base de datos


La fuente dice: "El uso de las posiciones de columna está en desuso porque la sintaxis se ha eliminado del estándar SQL". Lamentablemente, esto está mal: nunca se elimina nada de la Norma, lo que, irónicamente, es la razón por la que todavía tenemos HAVINGdécadas después de que las tablas derivadas lo "desaprobaran".
cuando

Ligeramente pedante, pero la cita no es correcta, por ejemplo, considere SELECT 1 FROM T HAVING COUNT(*) >= 1;: no hace referencia a columnas en la GROUP BYcláusula (no hay ninguna) ni a columnas en funciones agregadas (la consulta no hace referencia a ninguna columna).
cuando

0

Mientras trabajaba en un proyecto, esta también fue mi pregunta. Como se indicó anteriormente, HAVING verifica la condición en el resultado de la consulta ya encontrado. Pero WHERE es para verificar la condición mientras se ejecuta la consulta.

Permítanme dar un ejemplo para ilustrar esto. Supongamos que tiene una tabla de base de datos como esta.

usertable {int userid, date datefield, int dailyincome}

Supongamos que las siguientes filas están en la tabla:

1, 2011-05-20, 100

1, 2011-05-21, 50

1, 2011-05-30, 10

2, 2011-05-30, 10

2, 2011-05-20, 20

Ahora, queremos obtener el useridsy sum(dailyincome)cuyosum(dailyincome)>100

Si escribimos:

SELECCIONE userid, sum (dailyincome) DESDE usertable WHERE sum (dailyincome)> 100 GROUP BY userid

Esto sera un error. La consulta correcta sería:

SELECCIONE ID de usuario, suma (ingreso diario) DESDE GRUPO utilizable POR ID de usuario TENIENDO suma (ingreso diario)> 100


0

La cláusula WHERE se usa para comparar valores en la tabla base, mientras que la cláusula HAVING se puede usar para filtrar los resultados de funciones agregadas en el conjunto de resultados de la consulta ¡Haga clic aquí !


0

Cuando GROUP BY no se usa, las cláusulas WHERE y HAVING son esencialmente equivalentes.

Sin embargo, cuando se usa GROUP BY:

  • La cláusula WHERE se usa para filtrar registros de un resultado. El filtrado se produce antes de realizar cualquier agrupación.
  • La cláusula HAVING se usa para filtrar valores de un grupo (es decir, para verificar las condiciones después de que se haya realizado la agregación en grupos).

-1

Utilizo HAVING para restringir una consulta basada en los resultados de una función agregada. Por ejemplo, seleccione * en el grupo blahblahblah por ALGO que tenga un conteo (ALGO)> 0


-1

Puede ser solo que el tema de "donde" es una fila, mientras que el tema de "tener" es un grupo. Estoy en lo cierto?


3
Debe estar seguro antes de publicar una respuesta. Esto podría ser engañoso para los demás.
pippin1289
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.