Cuando empiezas a trabajar con reportes y análisis de datos, llega un momento donde WHERE ya no es suficiente. Ahí entra HAVING, una cláusula fundamental en SQL Server.
HAVING se utiliza para filtrar resultados después de aplicar GROUP BY, permitiendo crear análisis empresariales reales como:
Clientes que compraron más de cierto monto Categorías con muchas ventas Productos más vendidos
En este artículo aprenderás:
Qué es HAVING Diferencia entre WHERE y HAVING Casos reales empresariales Ejercicios tipo entrevista Buenas prácticas
¿Qué es HAVING?
HAVING filtra grupos generados por GROUP BY.
Se usa normalmente junto con:
COUNT() SUM() AVG() MAX() MIN()
Diferencia entre WHERE y HAVING
WHERE
Filtra antes del agrupamiento.
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT *
FROM Ventas
WHERE Total > 100 ;
Filtra ventas individuales.
HAVING
Filtra después del GROUP BY.
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Categoria,
SUM (Total) AS TotalVendido
FROM Ventas
GROUP BY Categoria
HAVING SUM (Total) > 1000 ;
Filtra categorías completa
Dataset completo (copiar y ejecutar)
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
IF OBJECT_ID('Ventas' , 'U' ) IS NOT NULL
DROP TABLE Ventas;
CREATE TABLE Ventas (
IdVenta INT IDENTITY (1 ,1 ) PRIMARY KEY,
Producto VARCHAR (100 ) NOT NULL ,
Categoria VARCHAR (50 ) NOT NULL ,
Cliente VARCHAR (100 ) NOT NULL ,
Total DECIMAL (10 ,2 ) NOT NULL ,
FechaVenta DATE NOT NULL
);
INSERT INTO Ventas (Producto, Categoria, Cliente, Total, FechaVenta)
VALUES
('Laptop' , 'Tecnología' , 'Juan Pérez' , 2500.00 , '2026-01-10' ),
('Mouse' , 'Tecnología' , 'Ana López' , 80.00 , '2026-01-11' ),
('Teclado' , 'Tecnología' , 'Juan Pérez' , 150.00 , '2026-01-12' ),
('Monitor' , 'Tecnología' , 'Carlos Ruiz' , 900.00 , '2026-01-13' ),
('Silla' , 'Muebles' , 'Ana López' , 450.00 , '2026-01-14' ),
('Escritorio' , 'Muebles' , 'Juan Pérez' , 700.00 , '2026-01-15' ),
('Tablet' , 'Tecnología' , 'Carlos Ruiz' , 1200.00 , '2026-01-16' );
Caso real: categorías con ventas mayores a 2000
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Categoria,
SUM (Total) AS TotalVendido
FROM Ventas
GROUP BY Categoria
HAVING SUM (Total) > 2000 ;
Clientes con más de una compra
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Cliente,
COUNT (* ) AS CantidadCompras
FROM Ventas
GROUP BY Cliente
HAVING COUNT (* ) > 1 ;
Clientes que gastaron más de 1000
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Cliente,
SUM (Total) AS TotalGastado
FROM Ventas
GROUP BY Cliente
HAVING SUM (Total) > 1000 ;
Productos con pocas ventas
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Producto,
COUNT (* ) AS TotalVentas
FROM Ventas
GROUP BY Producto
HAVING COUNT (* ) = 1 ;
Detecta productos con baja rotación.
WHERE + HAVING juntos
Puedes usar ambos.
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Categoria,
SUM (Total) AS TotalVendido
FROM Ventas
WHERE Total > 100
GROUP BY Categoria
HAVING SUM (Total) > 1000 ;
¿Qué pasa aquí?
WHERE Primero elimina ventas menores o iguales a 100.
GROUP BY Luego agrupa por categoría.
HAVING Finalmente filtra grupos mayores a 1000.
EJERCICIOS
Nivel entrevista real
Obtener:
Categoría Cantidad de ventas Total vendido Solo categorías con total mayor a 3000
SOLUCIÓN
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Categoria,
COUNT (* ) AS CantidadVentas,
SUM (Total) AS TotalVendido
FROM Ventas
GROUP BY Categoria
HAVING SUM (Total) > 3000 ;
Ejercicio tipo empresa
Obtener:
Clientes con más de una compra Total gastado Ordenados del mayor al menor
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL SELECT
Cliente,
COUNT (* ) AS CantidadCompras,
SUM (Total) AS TotalGastado
FROM Ventas
GROUP BY Cliente
HAVING COUNT (* ) > 1
ORDER BY TotalGastado DESC ;