En este artículo, aprenda cuándo usar DÓNDE y TENER. Ambos realizan funciones similares, pero para diferentes propósitos!
Todos los ejemplos de este artículo se basan en Microsoft SQL Server Management Studio y la base de datos AdventureWorks2012. Puede comenzar a usar estas herramientas gratuitas utilizando mi guía Introducción a SQL Server.
¿Cómo se diferencian Dónde y Tener?
Cuando se trabaja con SQL más avanzado, puede no estar claro cuándo tiene sentido usar una cláusula WHERE frente a una cláusula HAVING.
Aunque parece que ambas cláusulas hacen lo mismo, lo hacen de diferentes maneras. De hecho, sus funciones se complementan entre sí.
- Una cláusula WHERE se usa es filtrar registros de un resultado. El filtro se produce antes de realizar cualquier agrupación.
- Se utiliza una cláusula HAVING para filtrar valores de un grupo.
Antes de continuar, revisemos el formato de una instrucción SQL. Es
SELECTFROMWHEREGROUP BYHAVING
Para ayudar a mantener las cosas bien, me gusta pensar en el orden de ejecución de las sentencias SQL de arriba a abajo. Eso significa que la cláusula WHERE se aplica primero al resultado y luego, las filas restantes se resumen de acuerdo con el GRUPO BY.
cláusula WHERE
La cláusula WHERE se utiliza para filtrar filas de los resultados. Por ejemplo
SELECT COUNT(SalesOrderID)FROM Sales.SalesOrderDetail
Devuelve 121,317 como de la cuenta, mientras que, la consulta
SELECT COUNT(SalesOrderID)FROM Sales.SalesOrderDetailWHERE UnitPrice > 200
Devuelve 48,159 como el conde. Esto se debe a que la cláusula WHERE filtra los 73,158 detalles de los pedidos de venta cuyo precio unitario es menor o igual a 200 de los resultados.
Cláusula HAVING
La cláusula HAVING se usa para filtrar valores en un GRUPO POR. Puede usarlos para filtrar grupos como
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SalesOrderID > 50000
, pero su verdadero poder radica en su capacidad de comparar y filtrar según los resultados de funciones agregadas. Por ejemplo, puede seleccionar todos los pedidos que totalicen más de $10,000
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000
Dado que la visibilidad de la cláusula WHERE es una fila a la vez, no hay forma de que evalúe la SUMA de todos los ID de venta. La cláusula HAVING se evalúa después de crear el agrupamiento.
Combinando los dos: WHERE y HAVING
Cuando las sentencias SQL tienen una cláusula WHERE y una cláusula HAVING, tenga en cuenta que la cláusula WHERE se aplica primero, luego los resultados se agrupan y, finalmente, los grupos se filtran de acuerdo con la cláusula HAVING.
En muchos casos, puede colocar la condición WHERE en la cláusula HAVING, como
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000 AND SalesOrderID > 50000
Frente a
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailWHERE SalesOrderID > 50000GROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000
Si puede poner la condición desde la cláusula where en la cláusula having, ¿por qué preocuparse por el DÓNDE? ¿Puedo usar esta consulta?
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000 AND LineTotal > 10
En realidad, esa consulta genera un error. La columna LineTotal no forma parte de la lista de grupos por campos ni es el resultado de un total agregado.
Para ser válida, la cláusula having solo puede comparar resultados de funciones agregadas o parte de columna del grupo by.
Para ser válida, la consulta debe reescribirse como
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailWHERE LineTotal > 100GROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000
Para resumir la diferencia entre DÓNDE y TENER:
- DONDE se utiliza para filtrar registros antes de que se produzca cualquier agrupación.
- HAVING se usa para filtrar valores después de que hayan sido grupos. Solo se pueden incluir columnas o expresiones en el grupo en las condiciones de la cláusula HAVING