EVERY e uma funcao de agregacao que reduz um grupo de valores booleanos a um so: ela retorna true apenas quando a condicao vale para todas as linhas contadas do grupo. E o sinonimo padrao de BOOL_AND e e exatamente o que voce usa quando a pergunta e "todas as linhas satisfazem esta regra?".
Sintaxe basica
EVERY recebe uma expressao booleana avaliada por linha. O resultado e true se todas as linhas contadas deram true, e false se ao menos uma deu false.
SELECT dept, EVERY(salary > 0) AS all_paid
FROM employees
GROUP BY dept;
Para cada departamento verificamos que todo funcionario tem salario positivo. Se um unico funcionario tiver salary <= 0, a agregacao retorna false.
EVERY se comporta como um E logico sobre as linhas:
- todas
true -> true
- ao menos uma
false -> false
- nenhum valor conhecido
true/false para contar -> NULL
Essa ultima linha importa: um agregado SQL nao retorna true para um grupo vazio. O PostgreSQL retorna NULL (desconhecido) quando nao ha nada a reduzir, entao voce precisa tratar esse caso de forma explicita em vez de supor que seja "verdadeiro por vacuidade".
Roll-ups de validacao
O uso mais comum e reduzir varias linhas de detalhe a um unico indicador de estado. O caso classico: "todos os itens do pedido foram enviados?".
SELECT user_id,
EVERY(status = 'shipped') AS fully_shipped,
COUNT(*) AS line_items
FROM orders
GROUP BY user_id;
Uma unica linha com status <> 'shipped' muda fully_shipped para false. E ideal para dashboards e relatorios: uma linha por usuario em vez de recalcular a condicao no codigo da aplicacao.
EVERY combina naturalmente com HAVING quando voce quer apenas grupos "limpos":
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 versus BOOL_AND
Funcionalmente EVERY(x) e BOOL_AND(x) sao identicos no PostgreSQL; sao sinonimos. A diferenca e pura legibilidade:
EVERY esta no padrao SQL e se le como uma frase comum: "every order is shipped".
BOOL_AND deixa explicita a natureza booleana para quem pensa em flags.
SELECT EVERY(amount > 0) FROM orders;
SELECT BOOL_AND(amount > 0) FROM orders;
Dica: use EVERY em relatorios e views lidas por analistas, e BOOL_AND (com sua dupla BOOL_OR) em codigo de infraestrutura, para que a intencao "todas / ao menos uma" fique obvia num relance.
Tratamento de NULL
Esta e a principal armadilha. EVERY ignora as linhas em que o argumento e NULL, assim como os demais agregados.
SELECT EVERY(status = 'shipped') AS result
FROM orders
WHERE id IN (1, 2);
- Se uma linha tem
status IS NULL, entao status = 'shipped' resulta em NULL, e essa linha nao e contada.
- Se, apos descartar as linhas
NULL, nenhuma linha sobrar no grupo, EVERY retorna NULL, e nao true.
Gotcha: voce pode supor que um status NULL "reprova" a verificacao, mas ele e ignorado em silencio. Se NULL deve contar como violacao, normalize a expressao de forma explicita:
SELECT EVERY(COALESCE(status, 'pending') = 'shipped') AS strict
FROM orders
GROUP BY user_id;
Envolva o proprio agregado em COALESCE se preferir que um grupo totalmente vazio seja lido como falha em vez de NULL.
MySQL e ClickHouse
O EVERY padrao nao esta disponivel em todo lugar:
- PostgreSQL — suporte completo a
EVERY e BOOL_AND.
- MySQL — nao tem nem
EVERY nem BOOL_AND. Emule com MIN: MIN(condition) vale 1 somente quando a condicao e verdadeira em toda parte.
SELECT user_id, MIN(amount > 0) = 1 AS all_positive
FROM orders
GROUP BY user_id;
- ClickHouse — oferece
min e varios combinadores praticos; o caminho idiomatico e o mesmo truque com min(cond) ou o agregado minIf.
Lembre do essencial: EVERY significa "todas as linhas contadas passaram na verificacao", ignora NULL e retorna NULL (nao true) num grupo vazio. Para validacao estrita, decida o destino do NULL de forma explicita com COALESCE dentro do argumento ou ao redor do resultado.
EVERYe uma funcao de agregacao que reduz um grupo de valores booleanos a um so: ela retornatrueapenas quando a condicao vale para todas as linhas contadas do grupo. E o sinonimo padrao deBOOL_ANDe e exatamente o que voce usa quando a pergunta e "todas as linhas satisfazem esta regra?".Sintaxe basica
EVERYrecebe uma expressao booleana avaliada por linha. O resultado etruese todas as linhas contadas deramtrue, efalsese ao menos uma deufalse.SELECT dept, EVERY(salary > 0) AS all_paid FROM employees GROUP BY dept;Para cada departamento verificamos que todo funcionario tem salario positivo. Se um unico funcionario tiver
salary <= 0, a agregacao retornafalse.EVERYse comporta como um E logico sobre as linhas:true->truefalse->falsetrue/falsepara contar ->NULLEssa ultima linha importa: um agregado SQL nao retorna
truepara um grupo vazio. O PostgreSQL retornaNULL(desconhecido) quando nao ha nada a reduzir, entao voce precisa tratar esse caso de forma explicita em vez de supor que seja "verdadeiro por vacuidade".Roll-ups de validacao
O uso mais comum e reduzir varias linhas de detalhe a um unico indicador de estado. O caso classico: "todos os itens do pedido foram enviados?".
SELECT user_id, EVERY(status = 'shipped') AS fully_shipped, COUNT(*) AS line_items FROM orders GROUP BY user_id;Uma unica linha com
status <> 'shipped'mudafully_shippedparafalse. E ideal para dashboards e relatorios: uma linha por usuario em vez de recalcular a condicao no codigo da aplicacao.EVERYcombina naturalmente comHAVINGquando voce quer apenas grupos "limpos":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 versus BOOL_AND
Funcionalmente
EVERY(x)eBOOL_AND(x)sao identicos no PostgreSQL; sao sinonimos. A diferenca e pura legibilidade:EVERYesta no padrao SQL e se le como uma frase comum: "every order is shipped".BOOL_ANDdeixa explicita a natureza booleana para quem pensa em flags.-- mesmo resultado SELECT EVERY(amount > 0) FROM orders; SELECT BOOL_AND(amount > 0) FROM orders;Dica: use
EVERYem relatorios e views lidas por analistas, eBOOL_AND(com sua duplaBOOL_OR) em codigo de infraestrutura, para que a intencao "todas / ao menos uma" fique obvia num relance.Tratamento de NULL
Esta e a principal armadilha.
EVERYignora as linhas em que o argumento eNULL, assim como os demais agregados.SELECT EVERY(status = 'shipped') AS result FROM orders WHERE id IN (1, 2); -- suponha que a linha 2 tem status IS NULLstatus IS NULL, entaostatus = 'shipped'resulta emNULL, e essa linha nao e contada.NULL, nenhuma linha sobrar no grupo,EVERYretornaNULL, e naotrue.Gotcha: voce pode supor que um status
NULL"reprova" a verificacao, mas ele e ignorado em silencio. SeNULLdeve contar como violacao, normalize a expressao de forma explicita:SELECT EVERY(COALESCE(status, 'pending') = 'shipped') AS strict FROM orders GROUP BY user_id;Envolva o proprio agregado em
COALESCEse preferir que um grupo totalmente vazio seja lido como falha em vez deNULL.MySQL e ClickHouse
O
EVERYpadrao nao esta disponivel em todo lugar:EVERYeBOOL_AND.EVERYnemBOOL_AND. Emule comMIN:MIN(condition)vale1somente quando a condicao e verdadeira em toda parte.-- MySQL: equivalente de EVERY(amount > 0) SELECT user_id, MIN(amount > 0) = 1 AS all_positive FROM orders GROUP BY user_id;mine varios combinadores praticos; o caminho idiomatico e o mesmo truque commin(cond)ou o agregadominIf.Lembre do essencial:
EVERYsignifica "todas as linhas contadas passaram na verificacao", ignoraNULLe retornaNULL(naotrue) num grupo vazio. Para validacao estrita, decida o destino doNULLde forma explicita comCOALESCEdentro do argumento ou ao redor do resultado.