SQL COUNT()
A Ana vai mandar a newsletter de fim de ano da Loja Aurora por email. Antes, ela precisa de três números: quantos clientes a loja tem, quantos deles têm email cadastrado e de quantas cidades diferentes eles são. As três perguntas começam com "quantos", e quem responde todas é a mesma função: COUNT() ("contar", em inglês). Só que cada pergunta pede um jeito diferente de usá-la, e confundir os três é um dos erros mais comuns de quem começa.
COUNT(*): contar linhas.COUNT(coluna): contar os valores preenchidos de uma coluna, pulando osNULL.COUNT(DISTINCT coluna): contar os valores diferentes.- Como contar os que faltam (os clientes sem email).
- As armadilhas:
COUNT(vip)que conta todo mundo,COUNT('email')com aspas simples,= NULL. - Os erros reais do SQLite com
COUNT.
Se você ainda não leu, comece por O que são Funções Agregadas: lá está a ideia de "muitas linhas entram, uma sai".
A ideia: a lista de chamada
Imagine a professora com a lista de chamada da turma. Ela pode fazer três contas diferentes:
| Pergunta da professora | Como ela conta | Em SQL |
|---|---|---|
| Quantos alunos estão na lista? | Conta as linhas da lista, uma por aluno | COUNT(*) |
| Quantos deixaram o telefone? | Conta só as linhas em que o telefone está preenchido | COUNT(telefone) |
| De quantos bairros diferentes eles vêm? | Conta cada bairro uma vez só, mesmo que se repita | COUNT(DISTINCT bairro) |
A Loja Aurora tem exatamente esse caso na tabela clientes: 30 clientes, 3 sem email (os de id 7, 15 e 23) e várias cidades repetidas.
1. COUNT(*): quantas linhas
O jeito mais simples: COUNT(*) conta as linhas da tabela, sem olhar o que tem dentro delas.
SELECT COUNT(*) AS clientes FROM clientes;
- COUNT
- A função de contar.
- (*)
- O asterisco quer dizer "a linha toda".
COUNT(*)conta cada linha, mesmo uma linha cheia deNULL. É a única função agregada que aceita o*. - AS clientes
- Um apelido para a coluna do resultado (aula Apelidos (AS)). Sem ele, a coluna se chamaria
COUNT(*). - FROM clientes
- A tabela cujas linhas são contadas.
Com WHERE, o COUNT(*) conta só as linhas que passaram no filtro. Quantos pedidos tiveram frete grátis?
SELECT COUNT(*) AS frete_gratis FROM pedidos WHERE frete = 0;
Onze pedidos. Primeiro o WHERE separa as linhas com frete = 0, depois o COUNT(*) conta o que sobrou.
Experimente: a consulta conta todos os clientes. Acrescente um WHERE para contar só os de Teresina, a cidade da loja. Lembre: texto vai entre aspas simples.
SELECT COUNT(*) AS clientes FROM clientes;
SELECT COUNT(*) AS clientes FROM clientes WHERE cidade = 'Teresina';
2. COUNT(coluna): quantos valores preenchidos
Agora a pergunta da newsletter: quantos clientes têm email? Em vez do *, ponha o nome da coluna:
SELECT COUNT(*) AS clientes,
COUNT(email) AS com_email,
COUNT(nascimento) AS com_nascimento
FROM clientes;
- COUNT(*)
- Conta as 30 linhas.
- COUNT(email)
- Conta as linhas em que
emailnão éNULL. Os três clientes sem email ficam de fora: 27. - COUNT(nascimento)
- Mesma ideia na coluna
nascimento: dois clientes (9 e 21) não informaram a data, então dá 28.
A regra é uma só: COUNT(coluna) conta os valores que não são NULL. Ele não olha se o valor é bonito, se é zero ou se é um texto vazio; só pergunta "tem algo aqui ou é desconhecido?".
O mesmo truque responde "quantos pedidos já foram entregues?", porque o pedido que ainda não chegou tem entregue_em NULL:
SELECT COUNT(*) AS pedidos,
COUNT(entregue_em) AS entregues
FROM pedidos;
90 pedidos, 85 entregues. Os outros 5 estão a caminho.
3. Contar os que faltam
A Ana quer ligar para os clientes sem email e pedir o endereço. Quantos são? Há dois caminhos, e os dois dão 3:
SELECT COUNT(*) - COUNT(email) AS sem_email FROM clientes;
SELECT COUNT(*) AS sem_email FROM clientes WHERE email IS NULL;
O primeiro faz uma conta de menos: todas as linhas menos as que têm email. O segundo filtra com IS NULL (aula IS NULL e IS NOT NULL) e conta as linhas que sobraram. O segundo é mais fácil de ler; o primeiro é útil quando você quer os dois números na mesma linha, ao lado de outras contas.
4. COUNT(DISTINCT coluna): quantos valores diferentes
A terceira pergunta: de quantas cidades são os clientes? Se você contar a coluna cidade, dá 30, porque todo cliente tem cidade. Mas Teresina aparece 10 vezes, São Paulo 7… A palavra DISTINCT ("distinto", "diferente") manda contar cada valor uma vez só:
SELECT COUNT(cidade) AS cidades,
COUNT(DISTINCT cidade) AS cidades_diferentes
FROM clientes;
- COUNT(cidade)
- 30: conta as cidades preenchidas, com repetição.
- COUNT(DISTINCT cidade)
- 8: primeiro tira as repetições (Teresina, São Paulo, Fortaleza, Recife, Parnaíba, Picos, Oeiras e Floriano), depois conta.
É o mesmo DISTINCT da aula SELECT DISTINCT, só que aqui ele trabalha dentro do COUNT. Ele responde perguntas ótimas sobre a loja:
SELECT COUNT(DISTINCT produto_id) AS produtos_vendidos FROM itens_pedido;
A tabela itens_pedido tem 220 linhas, mas os mesmos produtos aparecem em vários pedidos. Produtos diferentes que já foram vendidos pelo menos uma vez: 42. Como a loja tem 45 produtos, três nunca foram vendidos (você vai descobrir quais na aula LEFT JOIN).
O DISTINCT também pula o NULL
Na tabela fornecedores, os dois estrangeiros (de Portugal e da Argentina) têm estado NULL. Compare a lista com a contagem:
SELECT DISTINCT estado FROM fornecedores;
SELECT COUNT(DISTINCT estado) AS estados FROM fornecedores;
A lista tem 4 linhas, uma delas NULL. A contagem dá 3. Não é contradição: o SELECT DISTINCT mostra o NULL como um valor a mais, mas o COUNT, como toda função agregada, não conta NULL. Se alguém perguntar "quantos estados aparecem na lista?", confira se a pessoa quer contar o "sem estado" ou não.
5. COUNT(*), COUNT(1) ou COUNT(id)?
Você vai ver estas três formas por aí. Numa coluna que nunca é NULL, como a chave primária id, elas dão o mesmo número:
SELECT COUNT(*), COUNT(1), COUNT(id) FROM clientes;
COUNT(1) conta quantas vezes o número 1 "não é NULL", ou seja, uma vez por linha. Funciona, mas COUNT(*) diz melhor o que você quer ("conte as linhas") e é a forma que todo banco reconhece e otimiza. Use COUNT(*) para linhas e COUNT(coluna) só quando quiser pular os NULL daquela coluna.
6. Formas diferentes de contar os VIPs
Na tabela clientes, a coluna vip vale 1 para os clientes VIP e 0 para os outros. Quantos VIPs a loja tem? Primeiro, a armadilha:
SELECT COUNT(vip) AS vips FROM clientes;
Deu 30, a tabela inteira! O COUNT(vip) não pergunta se o valor é 1; pergunta se ele não é NULL. E o 0 não é NULL: é um valor conhecido, que quer dizer "não é VIP". Então todo mundo foi contado. As formas certas:
SELECT COUNT(*) AS vips FROM clientes WHERE vip = 1;
SELECT SUM(vip) AS vips FROM clientes;
As duas dão 5. A segunda funciona porque vip só tem 0 e 1: somar os uns é o mesmo que contar os VIPs (aula SUM()).
| Forma | Resultado | Quando usar |
|---|---|---|
COUNT(*) … WHERE vip = 1 | 5 (certo) | A forma mais clara. Use esta. |
SUM(vip) | 5 (certo) | Só para colunas 0/1, quando você quer esse número ao lado de outros, na mesma linha |
COUNT(vip) | 30 (errado) | Nunca para "quantos são 1": conta tudo que não é NULL |
Quando dá errado
SELECT COUNT * FROM produtos;
A mensagem: near "FROM": syntax error, "erro de sintaxe perto de FROM". Sem os parênteses, o SQLite não enxerga uma função: lê COUNT como o nome de uma coluna e o * como "vezes", e fica esperando o número da multiplicação. Quando chega o FROM, ele desiste. Repare que a mensagem aponta o FROM, e não o COUNT: o erro de sintaxe aparece onde o SQLite percebeu o problema, que às vezes é um pouco depois de onde ele está.
Como consertar: COUNT(*), com os parênteses.
Em vez de errar, a consulta abaixo dá um resultado errado, sem aviso nenhum:
SELECT COUNT('email') AS com_email FROM clientes;
O que aconteceu: deu 30, e não 27. Com aspas simples, 'email' é o texto "email", igual em todas as linhas, e um texto nunca é NULL. O COUNT contou 30 vezes a palavra "email".
Como consertar: nome de coluna vai sem aspas: COUNT(email). Aspas simples são só para texto. E aspas duplas? Neste editor, "email" é um nome de coluna, então COUNT("email") funciona e dá 27. Com um nome que não existe, como COUNT("e-mail"), o SQLite responde no such column: "e-mail" - should this be a string literal in single-quotes? ("não existe a coluna "e-mail"; isto devia ser um texto entre aspas simples?"). Escreva os nomes de coluna sem aspas e em minúsculas.
= NULL
SELECT COUNT(*) AS sem_email FROM clientes WHERE email = NULL;
O que aconteceu: deu 0, mas são 3. Qualquer comparação com NULL usando = dá "desconhecido", nunca "verdadeiro", e o WHERE só deixa passar o verdadeiro. Nenhuma linha passou, e contar nada dá zero (veja O Valor NULL).
Como consertar: WHERE email IS NULL.
A Ana quer contar as combinações diferentes de cidade e estado:
SELECT COUNT(DISTINCT cidade, estado) FROM clientes;
A mensagem: wrong number of arguments to function COUNT(), "número errado de argumentos para a função COUNT()". No SQLite, o COUNT(DISTINCT …) aceita uma coluna só.
Como consertar: para contar combinações, conte as linhas de um SELECT DISTINCT cidade, estado, o que você aprende a fazer numa consulta só na aula Subconsultas. Ou agrupe com GROUP BY em várias colunas e veja quantas linhas saem.
- MySQL e MariaDB aceitam várias colunas no
COUNT(DISTINCT …):COUNT(DISTINCT cidade, estado)conta as combinações diferentes que não têmNULL. No SQLite e no padrão, é uma coluna só. - SQL Server:
COUNTdevolve umint(até uns 2,1 bilhões). Para tabelas maiores existeCOUNT_BIG, que devolvebigint. - PostgreSQL:
COUNTdevolvebigint.
SELECT COUNT(DISTINCT cidade, estado) FROM clientes;
Referência rápida
| Escrita | Conta | Na Loja Aurora |
|---|---|---|
COUNT(*) | Todas as linhas | 30 clientes |
COUNT(coluna) | As linhas em que a coluna não é NULL | COUNT(email) = 27 |
COUNT(DISTINCT coluna) | Os valores diferentes, sem contar NULL | COUNT(DISTINCT cidade) = 8 |
COUNT(*) - COUNT(coluna) | As linhas em que a coluna é NULL | 3 sem email |
COUNT(*) … WHERE cond | As linhas que passaram no filtro | WHERE vip = 1 → 5 |
| Sem nenhuma linha | Sempre 0, nunca NULL |
| Mensagem do SQLite | Quer dizer |
|---|---|
near "FROM": syntax error | Faltou o parêntese em COUNT * |
wrong number of arguments to function COUNT() | Mais de uma coluna dentro do COUNT(DISTINCT …) |
misuse of aggregate function COUNT() | COUNT dentro do WHERE (veja HAVING) |
Exercícios
1. Quantos pedidos
Complete para contar todas as linhas da tabela pedidos:
2. Quantos têm nascimento
Complete para contar só os clientes que informaram a data de nascimento:
3. Vendedores diferentes
Complete para contar quantos funcionários diferentes já atenderam pedidos:
4. A coluna descontinuado vale 0 ou 1 em todos os 45 produtos, e só 2 são 1. Quanto dá SELECT COUNT(descontinuado) FROM produtos;?
5. SELECT DISTINCT estado FROM fornecedores; mostra 4 linhas (PI, CE, SP e NULL). Quanto dá COUNT(DISTINCT estado)?
6. O que devolve COUNT(*) quando o WHERE não deixa passar nenhuma linha?
Missão final: o relatório da newsletter
Missão: monte, numa linha só, o relatório que a Ana precisa: o total de clientes (clientes), quantos têm email (com_email), quantos não têm (sem_email) e de quantas cidades diferentes eles são (cidades). Use esses apelidos, nessa ordem.
SELECT COUNT(*) AS clientes FROM clientes;
SELECT COUNT(*) AS clientes,
COUNT(email) AS com_email,
COUNT(*) - COUNT(email) AS sem_email,
COUNT(DISTINCT cidade) AS cidades
FROM clientes;
Resumo
COUNT(*)conta linhas, inclusive as que têmNULL.COUNT(coluna)conta os valores que não sãoNULL. Zero e texto vazio contam; só oNULLfica de fora.COUNT(DISTINCT coluna)conta os valores diferentes, também sem oNULL. No SQLite, uma coluna só.- Os que faltam:
COUNT(*) - COUNT(coluna)ouCOUNT(*) … WHERE coluna IS NULL. Nunca= NULL. - Para "quantos são 1" numa coluna 0/1, use
WHERE coluna = 1(ouSUM), nuncaCOUNT(coluna). COUNTsem nenhuma linha dá 0. Nome de coluna vai sem aspas:COUNT('email')conta um texto, e dá o total de linhas.