Tema SQL

Filtro sobre agregados (HAVING)

Filtra grupos ya formados por GROUP BY usando condiciones sobre SUM, COUNT, AVG, etc. No sustituye a WHERE: cada uno opera en una fase distinta del procesamiento lógico.

Todos los temas

129 tema(s) · elige uno para abrirlo

SELECT básico INNER JOIN LEFT JOIN Filtro sobre agregados (HAVING) Subconsulta escalar en WHERE INSERT: nuevas filas UPDATE: modificar filas existentes DELETE UNION / UNION ALL CTE (WITH) DISTINCT EXISTS (subconsulta) CASE (expresión condicional) GROUP BY ORDER BY RIGHT JOIN CROSS JOIN CREATE TABLE CREATE INDEX CREATE VIEW ALTER TABLE TRUNCATE TABLE MERGE / UPSERT Tipos de datos SQL WHERE: predicados y filtros LIMIT, OFFSET y FETCH LIKE y comodines IN y BETWEEN ANY, SOME y ALL Funciones de agregación Funciones escalares (texto, número,... COALESCE, NULLIF e IFNULL/ISNULL FULL OUTER JOIN SELF JOIN Subconsulta correlacionada INTERSECT y EXCEPT / MINUS CTE recursiva (WITH RECURSIVE) Funciones de ventana (OVER) DROP VIEW DROP INDEX DROP TABLE CREATE DATABASE Restricciones: NOT NULL, UNIQUE, PRI... FOREIGN KEY (clave foránea) Secuencias e identidad (AUTO_INCREME... Tablas temporales GRANT y REVOKE (DCL) Transacciones (BEGIN, COMMIT, ROLLBA... Triggers (disparadores) Procedimientos almacenados Funciones definidas por el usuario JSON en SQL LATERAL y APPLY (CROSS / OUTER) PIVOT y UNPIVOT RETURNING y OUTPUT FETCH … WITH TIES y OFFSET/FETCH DISTINCT ON (PostgreSQL) TABLESAMPLE FOR UPDATE, SKIP LOCKED y NOWAIT FIND_IN_SET() (MySQL / MariaDB) GROUP_CONCAT() (MySQL / MariaDB) IF() (MySQL / MariaDB) IFNULL() (MySQL / MariaDB) NULLIF() (MySQL / MariaDB) FIELD() (MySQL / MariaDB) ELT() (MySQL / MariaDB) STR_TO_DATE() (MySQL / MariaDB) DATE_FORMAT() (MySQL / MariaDB) TIMESTAMPDIFF() (MySQL / MariaDB) UUID() (MySQL / MariaDB) RAND() (MySQL / MariaDB) CONCAT_WS() (MySQL / MariaDB) SUBSTRING_INDEX() (MySQL / MariaDB) JSON_EXTRACT() (MySQL / MariaDB) JSON_UNQUOTE() (MySQL / MariaDB) MAKE_SET() (MySQL / MariaDB) EXPORT_SET() (MySQL / MariaDB) SLEEP() (MySQL / MariaDB) BENCHMARK() (MySQL / MariaDB) STRING_AGG() (SQL Server) ISNULL() (SQL Server) GETDATE() (SQL Server) SYSDATETIME() (SQL Server) DATEDIFF() (SQL Server) DATEADD() (SQL Server) IIF() (SQL Server) CHOOSE() (SQL Server) TRY_CAST / TRY_CONVERT (SQL Server) NEWID() (SQL Server) generate_series() (PostgreSQL) unnest() (PostgreSQL) array_agg() (PostgreSQL) jsonb_build_object() (PostgreSQL) jsonb_each() (PostgreSQL) to_tsvector() (PostgreSQL) to_tsquery() (PostgreSQL) set_config() (PostgreSQL) current_setting() (PostgreSQL) pg_sleep() (PostgreSQL) LAST_INSERT_ID() (MySQL / MariaDB) MATCH() … AGAINST() (MySQL / MariaDB... INSERT … ON DUPLICATE KEY UPDATE (My... UNIX_TIMESTAMP() / FROM_UNIXTIME() (... JSON_TABLE() (MySQL / MariaDB) REGEXP / RLIKE (MySQL / MariaDB) CONV() (MySQL / MariaDB) QUOTE() (MySQL / MariaDB) INSERT IGNORE (MySQL / MariaDB) ANY_VALUE() (MySQL / MariaDB) FOR JSON (SQL Server) CROSS APPLY / OUTER APPLY (SQL Serve... STUFF() (SQL Server) FORMAT() (SQL Server) TRY_PARSE() (SQL Server) EOMONTH() (SQL Server) STRING_SPLIT() (SQL Server) PIVOT (SQL Server) AT TIME ZONE (SQL Server) OPENJSON (SQL Server) date_trunc() (PostgreSQL) age() (PostgreSQL) jsonb_path_query / SQL/JSON (Postgre... Operadores de array (PostgreSQL) COPY (PostgreSQL) row_to_json / to_jsonb (PostgreSQL) Tipos rango (PostgreSQL) INTERVAL (PostgreSQL) FILTER en agregados (PostgreSQL) GENERATED … AS IDENTITY (PostgreSQL)

Descripción

WHERE restringe filas antes de agrupar; HAVING restringe grupos después de calcular agregados. Por tanto HAVING puede referenciar COUNT(*), SUM(importe) o expresiones derivadas de agregados, mientras WHERE no puede usar esos resultados directamente. Úsalo para reglas del tipo «solo clientes con más de N pedidos» o «departamentos cuyo salario medio supera un umbral». En motores con optimizador avanzado, condiciones redundantes pueden fusionarse, pero mantén la semántica clara para quien lea la consulta.

Estructura general

Forma habitual de la sentencia: orden de cláusulas, qué parte filtra, agrupa o proyecta columnas, y qué devuelve el motor. Cópiala como plantilla y sustituye nombres por tus tablas reales.

SQL
SELECT columnas_agrupadas, AGREGADO(...)
  FROM tabla
  [ WHERE condición_por_fila ]
  GROUP BY columnas_agrupadas
  HAVING condición_sobre_agregados;

Componentes

Cada componente tiene un papel concreto en la ejecución lógica de la sentencia. Léelos en orden: así entiendes qué puedes omitir, qué es obligatorio y qué expresiones son válidas en cada sitio según tu motor.

WHERE
Se evalúa sobre cada fila de la tabla (o join) antes de agrupar. Reduce el volumen de datos que entra en el GROUP BY y mejora el rendimiento cuando está soportado por índices.
GROUP BY
Define una fila de salida por cada combinación única de las columnas listadas. Todas las filas del grupo comparten esos valores de agrupación.
HAVING
Condición booleana sobre el grupo: comparaciones entre agregados, con constantes o entre sí. Es el lugar correcto para umbrales sobre COUNT/SUM/AVG tras agrupar.

Ejemplos

Ejemplo 1

SQL
SELECT usuario_id, COUNT(*) AS num_pedidos
FROM pedidos
GROUP BY usuario_id
HAVING COUNT(*) >= 3;

Ejemplo 2

SQL
SELECT region, SUM(ventas) AS t
FROM tiendas
GROUP BY region
HAVING SUM(ventas) > 1000;

Enlaces internos para seguir leyendo: SELECT, WHERE, JOIN, GROUP BY y el resto de la referencia SQL.

Los ejemplos son ilustrativos. En producción usa consultas parametrizadas (prepared statements), revisa índices y aplica el principio de menor privilegio en cuentas de base de datos.