Agregación · filtro por función

FILTER (WHERE ...) en agregaciones SQL

Filtra la entrada de un agregado concreto sin eliminar la fila para los demás cálculos de la misma consulta.

Lectura: 7–9 minSQL comprobadoPráctica con pistas
Contenido de esta guía

Respuesta rápida

FILTER (WHERE ...) limita las filas que recibe un agregado concreto. La fila puede seguir participando en otros agregados de la misma consulta.

Patrón
COUNT(*) FILTER (WHERE estado = 'enviado')

La idea clave es distinta de un WHERE general: WHERE elimina una fila de la entrada de toda la consulta; FILTER decide si esa fila entra en ese agregado.

Modelo mental: una entrada distinta para cada agregado

Imagina que cada agregado tiene su propia bandeja de entrada. COUNT(*) puede recibir las 18 filas de pedidos, mientras otro COUNT(*) FILTER (...) recibe únicamente los pedidos enviados. Ambos cálculos comparten la misma consulta, pero no necesariamente las mismas filas de entrada.

Patrón mental: filas de la consulta → condición de FILTER → agregado concreto.

Sintaxis básica

Agregado con filtro
AGREGADO(expresion) FILTER (WHERE condicion)

PostgreSQL documenta FILTER como parte de una expresión de agregado. SQLite también admite una cláusula FILTER y solo incluye en el agregado las filas cuya expresión sea verdadera.

Ejemplo: total de pedidos frente a pedidos enviados

Queremos tres medidas en una sola fila: todos los pedidos, cuántos están enviados y cuánto importe acumulan únicamente los enviados.

SQL comprobado en SQLite 3.46.1
SELECT COUNT(*) AS pedidos,
       COUNT(*) FILTER (WHERE estado = 'enviado') AS enviados,
       ROUND(SUM(total) FILTER (WHERE estado = 'enviado'), 2) AS importe_enviado
FROM pedidos;
Resultado comprobado con la base educativa
pedidosenviadosimporte_enviado
1891818,70

Las 18 filas llegan a COUNT(*). Solo las 9 filas con estado enviado llegan al segundo COUNT y al SUM filtrado.

FILTER vs WHERE, HAVING y CASE

Qué filtra cada opción
HerramientaQué decideMomento útil
WHEREQué filas llegan a la consulta antes de agruparLa condición debe afectar a todos los cálculos
FILTERQué filas recibe un agregado concretoNecesitas varias métricas condicionales en la misma fila
HAVINGQué grupos permanecen después de agregarFiltras grupos por un resultado agregado
CASE dentro del agregadoQué valor aporta cada fila al cálculoQuieres un patrón explícito y ampliamente portable

El patrón ya explicado en SUM(CASE WHEN ...) puede resolver muchos de los mismos problemas. FILTER hace visible que la condición pertenece al agregado, pero no debes asumir que todos los motores aceptan la misma sintaxis.

FILTER también funciona dentro de GROUP BY

Conteos por cliente
SELECT cliente_id,
       COUNT(*) AS pedidos,
       COUNT(*) FILTER (WHERE estado = 'enviado') AS enviados
FROM pedidos
GROUP BY cliente_id
ORDER BY cliente_id;

Cada fila de salida representa un cliente. Dentro de cada grupo, el primer conteo usa todas las filas y el segundo solo las enviadas.

Errores frecuentes

Usar WHERE cuando solo una métrica debía filtrarse

Si escribes WHERE estado = 'enviado', también reduces el COUNT(*) total. Usa FILTER cuando el filtro pertenezca a una medida y no al conjunto completo.

Confundir FILTER con HAVING

FILTER selecciona entradas de un agregado. HAVING se evalúa sobre los grupos ya formados y decide si una fila agregada permanece en el resultado.

Dar por portable una sintaxis del motor

PostgreSQL y SQLite documentan FILTER. Si tu proyecto apunta a otro motor, verifica su sintaxis; CASE dentro del agregado sigue siendo una alternativa clara para expresar la condición.

Práctica guiada

Intermedia · dos métricas condicionales

Separa pedidos de 200 € o más

Devuelve una sola fila con pedidos_200_mas y pedidos_menos_200 usando dos COUNT(*) FILTER (...).

Criterio de éxito: el resultado es 5 | 13.

Compatibilidad

PostgreSQL incluye FILTER (WHERE ...) en la sintaxis de sus expresiones de agregado. SQLite documenta la misma idea en su sintaxis de funciones agregadas. Para otros motores, consulta su documentación antes de copiar esta forma literalmente.

Qué debes recordar

  • FILTER modifica la entrada de un agregado concreto.
  • WHERE filtra las filas para la consulta completa.
  • HAVING filtra grupos después de agregar.
  • Es especialmente útil cuando una fila de salida contiene varias métricas con condiciones diferentes.
  • SUM(CASE WHEN ...) sigue siendo un patrón importante cuando buscas una alternativa explícita y portable.

Conceptos relacionados

Fuentes técnicas consultadas