Lembrando: funções agregadas são aquelas que trabalham com várias linhas de dados de uma vez e retornam um único resultado. No PostgreSQL, você vai usar bastante essas funções agregadas:
SUM()— soma dos dados.AVG()— cálculo da média.MIN()— encontra o valor mínimo.MAX()— encontra o valor máximo.COUNT()— conta as linhas.
Parece simples: você passa uma coluna ou expressão pra função e recebe o resultado. Mas o que acontece se na coluna aparecer um NULL?
Comportamento do NULL nas agregadas: visão rápida
É aqui que a parada fica interessante:
SUM()eAVG()ignoramNULL. Se pelo menos um registro temNULL, ele simplesmente não entra no cálculo. Faz sentido, né? Como a soma vai aumentar se alguém "não veio pra festa"? Ou como calcular a média se falta um valor?MIN()eMAX()também pulam oNULL. Eles acham o mínimo ou máximo só entre os dados que não sãoNULL. Então, se você procura o funcionário mais novo e alguém esqueceu de preencher a data de nascimento, oNULLnão vai ganhar.COUNT(*)conta todas as linhas, até as que têmNULL. JáCOUNT(coluna)só conta as linhas onde a coluna tem valor, ou seja,NULLé ignorado.
Bora ver isso na prática com exemplos.
Exemplos de uso das funções agregadas com NULL
Aqui está a tabela students_scores, que guarda as notas dos estudantes num teste:
| student_id | name | score |
|---|---|---|
| 1 | Alyssa | 85 |
| 2 | Bob | NULL |
| 3 | Charlie | 92 |
| 4 | Dana | NULL |
| 5 | Elena | 74 |
Agora vamos fazer uns queries e analisar os resultados:
- Soma de todas as notas:
SUM()
SELECT SUM(score) AS total_score
FROM students_scores;
Resultado:
| total_score |
|---|
| 251 |
Como você vê, os valores NULL foram simplesmente ignorados na soma. Pra Alyssa (85), Charlie (92) e Elena (74), a soma deu 251. Bob e Dana ficaram de fora.
- Média das notas:
AVG()
SELECT AVG(score) AS average_score
FROM students_scores;
Resultado:
| average_score |
|---|
| 83.67 |
De novo, NULL foi ignorado e a média foi calculada só pra quem tem nota: (85 + 92 + 74) / 3 = 83.67.
- Nota mínima e máxima:
MIN()eMAX()
SELECT
MIN(score) AS min_score,
MAX(score) AS max_score
FROM students_scores;
Resultado:
| min_score | max_score |
|---|---|
| 74 | 92 |
Aqui também é simples: NULL foi ignorado, e o mínimo ficou 74 e o máximo 92.
- Contando linhas:
COUNT(*)vsCOUNT(coluna)
SELECT
COUNT(*) AS total_rows,
COUNT(score) AS non_null_scores
FROM students_scores;
Resultado:
| total_rows | non_null_scores |
|---|---|
| 5 | 3 |
COUNT(*)contou todas as linhas, até as quescoreéNULL.COUNT(score)contou só as linhas onde a colunascoretem valor.
Casos práticos
Bora ver uns exemplos do mundo real.
Exemplo 1: Contando funcionários com salário informado e não informado
Imagina que temos uma tabela employees com salários.
| id | name | salary |
|---|---|---|
| 1 | Alex Lin | 50000 |
| 2 | Maria Chi | NULL |
| 3 | Anna Song | 60000 |
| 4 | Otto Art | NULL |
| 5 | Liam Park | 55000 |
Queremos saber quantos funcionários informaram o salário e quantos não.
SELECT
COUNT(*) AS total_employees,
COUNT(salary) AS employees_with_salary,
COUNT(*) - COUNT(salary) AS employees_without_salary
FROM employees;
Aqui:
COUNT(*)retorna o total de funcionários.COUNT(salary)conta quantos informaram o salário.- Pra saber quantos não informaram, é só subtrair um do outro.
Resultado
| total_employees | employees_with_salary | employees_without_salary |
|---|---|---|
| 5 | 3 | 2 |
Exemplo 2: Calculando o preço médio dos produtos com dados faltando
Você é dono de uma loja mágica, e na tabela products tem a coluna price, mas alguns produtos ainda não têm preço definido.
| id | name | price |
|---|---|---|
| 1 | Magic Wand | 150 |
| 2 | Enchanted Cloak | NULL |
| 3 | Potion Bottle | 75 |
| 4 | Spell Book | 200 |
| 5 | Crystal Ball | NULL |
Você quer saber o preço médio só dos produtos que têm preço definido.
SELECT AVG(price) AS average_price
FROM products;
Resultado:
| average_price |
|---|
| 141.6667 |
Se você quiser colocar um preço padrão pros produtos sem preço (tipo, deixar 0), pode usar a função COALESCE() que a gente vai ver na próxima aula.
Exemplo 3: Encontrando a idade mínima e máxima dos estudantes
Na tabela students tem a idade dos alunos, mas pra alguns a idade é desconhecida (NULL).
| id | name | age |
|---|---|---|
| 1 | Alex Lin | 20 |
| 2 | Maria Chi | NULL |
| 3 | Anna Song | 19 |
| 4 | Otto Art | 22 |
| 5 | Liam Park | NULL |
Queremos saber quem é o mais novo e o mais velho.
SELECT
MIN(age) AS youngest_student,
MAX(age) AS eldest_student
FROM students;
Resultado:
| youngest_student | eldest_student |
|---|---|
| 19 | 22 |
Esse query retorna a idade mínima e máxima só dos estudantes que têm idade informada. NULL é ignorado de novo.
Peculiaridades e pegadinhas
Quando você trabalha com NULL nas agregadas, é bom lembrar dessas paradas:
- Na soma
SUM()e na médiaAVG(),NULLnão entra no cálculo. Dá pra usar isso pra não somar valores "vazios". - Se quiser contar linhas com
NULLna coluna, usaCOUNT(*). - Usando
MIN()ouMAX(),NULLnão afeta o resultado. Mas se a coluna inteira for sóNULL, o resultado também vai serNULL.
Dicas pra lidar com NULL
- Pense no que você quer resolver. É importante saber se você precisa considerar
NULLno seu query. Às vezes, como noAVG(), ignorar é o certo. Outras vezes, como ao contar tudo, é bom incluir as linhas comNULL. - Use
COALESCE()quando precisar. Se quiser trocarNULLpor um valor padrão nos cálculos, a funçãoCOALESCE()vai ser sua amiga (mas isso é assunto pra próxima aula). - Não confunda
COUNT(*)comCOUNT(coluna). Essa é clássica pra quem tá começando. O primeiro conta todas as linhas, o segundo só as linhas com valor não nulo.
Agora você já sabe como o misterioso NULL pode mexer com as agregadas. Esse conhecimento vai te ajudar a evitar surpresas e usar o NULL a seu favor. Na próxima aula, vamos ver a função poderosa COALESCE() pra lidar com NULL de um jeito ainda mais esperto.
GO TO FULL VERSION