EVERY es una funcion de agregacion que reduce un grupo de valores booleanos a uno solo: devuelve true solo cuando la condicion se cumple en todas las filas contadas del grupo. Es el sinonimo estandar de BOOL_AND y es justo lo que necesitas cuando la pregunta es "cumplen todas las filas esta regla?".
Sintaxis basica
EVERY recibe una expresion booleana que se evalua por fila. El resultado es true si todas las filas contadas dieron true, y false si al menos una dio false.
SELECT dept, EVERY(salary > 0) AS all_paid
FROM employees
GROUP BY dept;
Para cada departamento comprobamos que todos los empleados tienen un salario positivo. Si un solo empleado tiene salary <= 0, la agregacion devuelve false.
EVERY se comporta como un Y logico sobre las filas:
- todas
true -> true
- al menos una
false -> false
- ningun valor conocido
true/false que contar -> NULL
Esa ultima linea importa: un agregado SQL no devuelve true para un grupo vacio. PostgreSQL devuelve NULL (desconocido) cuando no hay nada que plegar, asi que debes tratar ese caso de forma explicita en lugar de suponer que es "verdadero por vacuidad".
Roll-ups de validacion
El uso mas habitual es reducir muchas filas de detalle a un unico indicador de estado. El caso clasico: "se han enviado todas las lineas del pedido?".
SELECT user_id,
EVERY(status = 'shipped') AS fully_shipped,
COUNT(*) AS line_items
FROM orders
GROUP BY user_id;
Una sola fila con status <> 'shipped' pone fully_shipped en false. Es ideal para cuadros de mando e informes: una fila por usuario en lugar de recalcular la condicion en el codigo de la aplicacion.
EVERY encaja de forma natural con HAVING cuando solo quieres grupos "limpios":
SELECT u.country, EVERY(o.amount > 0) AS all_positive
FROM users u
JOIN orders o ON o.user_id = u.id
GROUP BY u.country
HAVING EVERY(o.amount > 0);
EVERY frente a BOOL_AND
Funcionalmente EVERY(x) y BOOL_AND(x) son identicos en PostgreSQL; son sinonimos. La diferencia es pura legibilidad:
EVERY esta en el estandar SQL y se lee como una frase normal: "every order is shipped".
BOOL_AND deja explicita la naturaleza booleana para quien piensa en banderas.
SELECT EVERY(amount > 0) FROM orders;
SELECT BOOL_AND(amount > 0) FROM orders;
Consejo: usa EVERY en informes y vistas que leen los analistas, y BOOL_AND (junto con su pareja BOOL_OR) en codigo interno, para que la intencion "todas / al menos una" se vea de un vistazo.
Tratamiento de NULL
Esta es la trampa principal. EVERY ignora las filas donde el argumento es NULL, igual que el resto de agregados.
SELECT EVERY(status = 'shipped') AS result
FROM orders
WHERE id IN (1, 2);
- Si una fila tiene
status IS NULL, entonces status = 'shipped' evalua a NULL y esa fila no se cuenta.
- Si, tras descartar las filas
NULL, no queda ninguna fila en el grupo, EVERY devuelve NULL, no true.
Gotcha: podrias suponer que un estado NULL "suspende" la comprobacion, pero se ignora en silencio. Si NULL debe contar como violacion, normaliza la expresion de forma explicita:
SELECT EVERY(COALESCE(status, 'pending') = 'shipped') AS strict
FROM orders
GROUP BY user_id;
Envuelve el propio agregado en COALESCE si prefieres que un grupo totalmente vacio se lea como un fallo en lugar de NULL.
MySQL y ClickHouse
El EVERY estandar no esta disponible en todas partes:
- PostgreSQL — soporte completo de
EVERY y BOOL_AND.
- MySQL — no tiene ni
EVERY ni BOOL_AND. Emulalo con MIN: MIN(condition) vale 1 solo cuando la condicion es cierta en todas partes.
SELECT user_id, MIN(amount > 0) = 1 AS all_positive
FROM orders
GROUP BY user_id;
- ClickHouse — ofrece
min y varios combinadores comodos; el camino idiomatico es el mismo truco con min(cond) o el agregado minIf.
Recuerda lo esencial: EVERY significa "todas las filas contadas pasaron la comprobacion", ignora NULL y devuelve NULL (no true) en un grupo vacio. Para una validacion estricta, decide el destino de NULL de forma explicita con COALESCE dentro del argumento o alrededor del resultado.
EVERYes una funcion de agregacion que reduce un grupo de valores booleanos a uno solo: devuelvetruesolo cuando la condicion se cumple en todas las filas contadas del grupo. Es el sinonimo estandar deBOOL_ANDy es justo lo que necesitas cuando la pregunta es "cumplen todas las filas esta regla?".Sintaxis basica
EVERYrecibe una expresion booleana que se evalua por fila. El resultado estruesi todas las filas contadas dierontrue, yfalsesi al menos una diofalse.SELECT dept, EVERY(salary > 0) AS all_paid FROM employees GROUP BY dept;Para cada departamento comprobamos que todos los empleados tienen un salario positivo. Si un solo empleado tiene
salary <= 0, la agregacion devuelvefalse.EVERYse comporta como un Y logico sobre las filas:true->truefalse->falsetrue/falseque contar ->NULLEsa ultima linea importa: un agregado SQL no devuelve
truepara un grupo vacio. PostgreSQL devuelveNULL(desconocido) cuando no hay nada que plegar, asi que debes tratar ese caso de forma explicita en lugar de suponer que es "verdadero por vacuidad".Roll-ups de validacion
El uso mas habitual es reducir muchas filas de detalle a un unico indicador de estado. El caso clasico: "se han enviado todas las lineas del pedido?".
SELECT user_id, EVERY(status = 'shipped') AS fully_shipped, COUNT(*) AS line_items FROM orders GROUP BY user_id;Una sola fila con
status <> 'shipped'ponefully_shippedenfalse. Es ideal para cuadros de mando e informes: una fila por usuario en lugar de recalcular la condicion en el codigo de la aplicacion.EVERYencaja de forma natural conHAVINGcuando solo quieres grupos "limpios":SELECT u.country, EVERY(o.amount > 0) AS all_positive FROM users u JOIN orders o ON o.user_id = u.id GROUP BY u.country HAVING EVERY(o.amount > 0);EVERY frente a BOOL_AND
Funcionalmente
EVERY(x)yBOOL_AND(x)son identicos en PostgreSQL; son sinonimos. La diferencia es pura legibilidad:EVERYesta en el estandar SQL y se lee como una frase normal: "every order is shipped".BOOL_ANDdeja explicita la naturaleza booleana para quien piensa en banderas.-- mismo resultado SELECT EVERY(amount > 0) FROM orders; SELECT BOOL_AND(amount > 0) FROM orders;Consejo: usa
EVERYen informes y vistas que leen los analistas, yBOOL_AND(junto con su parejaBOOL_OR) en codigo interno, para que la intencion "todas / al menos una" se vea de un vistazo.Tratamiento de NULL
Esta es la trampa principal.
EVERYignora las filas donde el argumento esNULL, igual que el resto de agregados.SELECT EVERY(status = 'shipped') AS result FROM orders WHERE id IN (1, 2); -- supongamos que la fila 2 tiene status IS NULLstatus IS NULL, entoncesstatus = 'shipped'evalua aNULLy esa fila no se cuenta.NULL, no queda ninguna fila en el grupo,EVERYdevuelveNULL, notrue.Gotcha: podrias suponer que un estado
NULL"suspende" la comprobacion, pero se ignora en silencio. SiNULLdebe contar como violacion, normaliza la expresion de forma explicita:SELECT EVERY(COALESCE(status, 'pending') = 'shipped') AS strict FROM orders GROUP BY user_id;Envuelve el propio agregado en
COALESCEsi prefieres que un grupo totalmente vacio se lea como un fallo en lugar deNULL.MySQL y ClickHouse
El
EVERYestandar no esta disponible en todas partes:EVERYyBOOL_AND.EVERYniBOOL_AND. Emulalo conMIN:MIN(condition)vale1solo cuando la condicion es cierta en todas partes.-- MySQL: equivalente de EVERY(amount > 0) SELECT user_id, MIN(amount > 0) = 1 AS all_positive FROM orders GROUP BY user_id;miny varios combinadores comodos; el camino idiomatico es el mismo truco conmin(cond)o el agregadominIf.Recuerda lo esencial:
EVERYsignifica "todas las filas contadas pasaron la comprobacion", ignoraNULLy devuelveNULL(notrue) en un grupo vacio. Para una validacion estricta, decide el destino deNULLde forma explicita conCOALESCEdentro del argumento o alrededor del resultado.