Wiki SQL
GROUP BY, HAVING e agregações
COUNT(*) conta linhas, COUNT(coluna) conta valores; HAVING filtra grupos; NULL vira um grupo.
Agregar é transformar muitas linhas em uma por grupo. As funções de agregação ignoram NULL, com uma exceção: COUNT(*), que conta linhas.
SELECT COUNT(*) AS linhas,
COUNT(valor) AS com_valor,
SUM(valor) AS soma,
AVG(valor) AS media
FROM pedidos;Saída
linhas | com_valor | soma | media ------ | --------- | ---- | ----- 10 | 9 | 3600 | 400
A média ignorou o pedido sem valor: é SUM(valor) / COUNT(valor), não dividido por todas as linhas. Se "sem valor" deveria contar como zero, diga isso com COALESCE(valor, 0).
HAVING filtra grupos
WHERE roda antes de agrupar; HAVING, depois. Filtro sobre o resultado de uma agregação só pode ir no HAVING.
SELECT cliente_id, COUNT(*) AS pedidos, SUM(valor) AS total
FROM pedidos
WHERE status <> 'cancelado'
GROUP BY cliente_id
HAVING COUNT(*) >= 2
ORDER BY total DESC;Saída
cliente_id | pedidos | total ---------- | ------- | ----- 1 | 2 | 1130 2 | 2 | 1050 3 | 2 | 180
NULL é um grupo
Para o GROUP BY, todos os NULL caem no mesmo grupo (embora NULL = NULL não seja verdadeiro).
SELECT cidade, COUNT(*) AS clientes
FROM clientes
GROUP BY cidade
ORDER BY clientes DESC, cidade;Saída
cidade | clientes --------- | -------- São Paulo | 2 NULL | 1 Campinas | 1 Curitiba | 1 Recife | 1
COUNT(DISTINCT)
SELECT COUNT(DISTINCT cliente_id) AS cliente_ids_distintos,
COUNT(DISTINCT data) AS dias_com_venda
FROM pedidos;Saída
cliente_ids_distintos | dias_com_venda --------------------- | -------------- 6 | 5
São 6 ids e não 5 clientes de verdade: o 9 do pedido órfão entra na conta. COUNT(DISTINCT) não sabe se a chave existe na outra tabela; isso é trabalho de um JOIN ou de uma regra de qualidade.
- Em grandes volumes,
COUNT(DISTINCT)exato é caro; Spark e Databricks têmapprox_count_distinct(HyperLogLog), com erro controlado. - Toda coluna do
SELECTque não está numa agregação precisa estar noGROUP BY(o SQLite deixa passar, o padrão e o Spark não).
Fontes
Conhecimento compartilhado pela Genesis Innovation.