SQL: Expressões Condicionais
Imagine que você está fazendo um pedido em um restaurante e o garçom pergunta: "Você prefere picante ou não-picante? Leve, médio, ou extra forte?" — isso é lógica condicional: dar respostas diferentes com base em situações diferentes. O CASE WHEN no SQL funciona da mesma forma: retornar valores diferentes com base em condições diferentes, tornando seus resultados de consulta mais flexíveis e significativos.
1. Conceitos Fundamentais
(1) Sintaxe Simple CASE
Simple CASE compara uma expressão contra múltiplos valores, semelhante a uma instrução switch em linguagens de programação.
CASE expressao
WHEN valor1 THEN resultado1
WHEN valor2 THEN resultado2
...
ELSE resultado_padrao
END
-- Retornar descrições em português com base no status do pedido
SELECT order_id, status,
CASE status
WHEN 'completed' THEN 'Concluído'
WHEN 'shipped' THEN 'Enviado'
WHEN 'pending' THEN 'Pendente'
WHEN 'cancelled' THEN 'Cancelado'
ELSE 'Status Desconhecido'
END AS descricao_status
FROM orders;
(2) Sintaxe Searched CASE
Searched CASE usa expressões condicionais, oferecendo mais flexibilidade para lógica complexa.
CASE
WHEN condicao1 THEN resultado1
WHEN condicao2 THEN resultado2
...
ELSE resultado_padrao
END
-- Classificar níveis salariais
SELECT first_name, last_name, salary,
CASE
WHEN salary >= 15000 THEN 'Alto'
WHEN salary >= 10000 THEN 'Médio'
WHEN salary >= 7000 THEN 'Padrão'
ELSE 'Nível Inicial'
END AS nivel_salarial
FROM employees;
>, <, LIKE, IS NULL e quaisquer outras condições. Searched CASE é recomendado para a maioria dos cenários por ser mais flexível.
(3) CASE no SELECT
Usar CASE na lista de colunas do SELECT permite avaliação condicional para cada linha, gerando novas colunas calculadas.
SELECT
CONCAT(first_name, last_name) AS nome,
salary,
CASE
WHEN salary >= 12000 THEN 'Sênior'
WHEN salary >= 8000 THEN 'Pleno'
ELSE 'Júnior'
END AS nivel
FROM employees;
(4) CASE no ORDER BY
Use CASE para definir regras de ordenação personalizadas para "ordenar por ordem especificada".
-- Ordenação personalizada por status: Pendente > Enviado > Concluído > Cancelado
SELECT order_id, status, total_amount
FROM orders
ORDER BY
CASE status
WHEN 'pending' THEN 1
WHEN 'shipped' THEN 2
WHEN 'completed' THEN 3
WHEN 'cancelled' THEN 4
END;
(5) CASE no GROUP BY
Combinado com funções de agregação, isso permite estatísticas condicionais (pivô de linhas para colunas), uma técnica comum em análise de dados.
-- Contar pedidos por status
SELECT
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS concluidos,
SUM(CASE WHEN status = 'shipped' THEN 1 ELSE 0 END) AS enviados,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pendentes,
SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelados
FROM orders;
(6) CASE no UPDATE
Use CASE em instruções UPDATE para atualizações condicionais em lote, completando múltiplas operações de lógica de atualização em uma única instrução SQL.
-- Ajustar salário com base no desempenho
UPDATE employees
SET salary = CASE
WHEN salary < 8000 THEN salary * 1.15
WHEN salary < 12000 THEN salary * 1.10
ELSE salary * 1.05
END;
(7) IF / IFNULL / COALESCE
O MySQL fornece funções condicionais mais concisas que o CASE:
| Função | Sintaxe | Finalidade |
|---|---|---|
IF |
IF(condicao, valor_verdadeiro, valor_falso) |
Escolha binária simples |
IFNULL |
IFNULL(expressao, substituicao) |
Retornar substituição quando NULL |
COALESCE |
COALESCE(valor1, valor2, ...) |
Retornar o primeiro valor não-NULL |
-- IF: escolha binária simples
SELECT IF(salary > 10000, 'Alto', 'Normal') AS nivel FROM employees;
-- IFNULL: lidar com NULL
SELECT IFNULL(department_id, 0) AS department_id FROM employees;
-- COALESCE: retornar primeiro não-NULL
SELECT COALESCE(commission, bonus, 0) AS bonus FROM employees;
COALESCE é uma função padrão SQL que suporta múltiplos argumentos; IFNULL é específica do MySQL e suporta apenas dois argumentos. COALESCE é recomendada para melhor compatibilidade.
2. Sintaxe Básica
(1) Sintaxe Completa do CASE WHEN
-- Simple CASE
CASE expressao
WHEN valor1 THEN resultado1
WHEN valor2 THEN resultado2
[ELSE resultado_padrao]
END
-- Searched CASE
CASE
WHEN condicao1 THEN resultado1
WHEN condicao2 THEN resultado2
[ELSE resultado_padrao]
END
(2) Sintaxe de Funções Condicionais
IF(condicao, valor_verdadeiro, valor_falso)
IFNULL(expressao, substituicao)
COALESCE(valor1, valor2, ..., valorN)
COALESCE pode substituir IFNULL e suporta múltiplos valores de fallback — é recomendada.
▶ Exemplo: Adicionar Rótulos de Status e Prioridade aos Pedidos (Dificuldade ⭐)
SELECT
order_id,
CONCAT(e.first_name, e.last_name) AS responsavel,
o.total_amount AS valor,
CASE status
WHEN 'completed' THEN '✅ Concluído'
WHEN 'shipped' THEN '🚚 Enviado'
WHEN 'pending' THEN '⏳ Pendente'
WHEN 'cancelled' THEN '❌ Cancelado'
ELSE '❓ Desconhecido'
END AS rotulo_status,
CASE
WHEN total_amount >= 3000 THEN 'Alta'
WHEN total_amount >= 1000 THEN 'Média'
ELSE 'Baixa'
END AS prioridade
FROM orders o
LEFT JOIN employees e ON o.employee_id = e.employee_id
ORDER BY
CASE
WHEN total_amount >= 3000 THEN 1
WHEN total_amount >= 1000 THEN 2
ELSE 3
END;
Saída:
order_id | responsavel | valor | rotulo_status | prioridade
---------+-------------+----------+------------------+-----------
1005 | ZhaoMin | 4100.00 | ✅ Concluído | Alta
1003 | ZhaoMin | 3200.00 | 🚚 Enviado | Alta
1006 | WangQiang | 2800.00 | ❌ Cancelado | Média
1001 | WangQiang | 2500.00 | ✅ Concluído | Média
1002 | WangQiang | 1800.00 | ✅ Concluído | Média
1004 | ZhangWei | 950.00 | ⏳ Pendente | Baixa
Abordagem da consulta:
- O primeiro CASE converte status em inglês para descrições com rótulos
- O segundo CASE classifica a prioridade pelo valor
- O CASE no ORDER BY ordena por prioridade
▶ Exemplo: Contar Funcionários por Nível Salarial por Departamento (Dificuldade ⭐⭐)
SELECT
d.department_name AS departamento,
COUNT(*) AS total,
SUM(CASE WHEN e.salary >= 12000 THEN 1 ELSE 0 END) AS salario_alto,
SUM(CASE WHEN e.salary >= 8000 AND e.salary < 12000 THEN 1 ELSE 0 END) AS salario_medio,
SUM(CASE WHEN e.salary < 8000 THEN 1 ELSE 0 END) AS salario_padrao,
AVG(e.salary) AS salario_medio_geral
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name
ORDER BY salario_medio_geral DESC;
Saída:
departamento | total | salario_alto | salario_medio | salario_padrao | salario_medio_geral
-------------+-------+-------------+---------------+----------------+--------------------
Technology | 2 | 1 | 1 | 0 | 10750.00
Sales | 2 | 1 | 1 | 0 | 9500.00
Marketing | 1 | 0 | 0 | 1 | 7500.00
NULL | 1 | 0 | 1 | 0 | 9000.00
Abordagem da consulta:
- GROUP BY agrupa por departamento
- Cada SUM(CASE ...) conta funcionários que atendem à condição, alcançando pivô de linhas para colunas
- Simultaneamente calcula o salário médio como referência
3. Cenários Comuns de Aplicação
(1) Cenário 1: Rótulos Dinâmicos — Marcar Funcionários com Base em Condições Multidimensionais
SELECT
CONCAT(e.first_name, e.last_name) AS nome,
d.department_name AS departamento,
e.salary,
CASE
WHEN e.salary >= 12000 AND d.department_name = 'Technology' THEN 'Equipe Técnica Principal'
WHEN e.salary >= 12000 THEN 'Funcionário Sênior'
WHEN e.salary >= 8000 AND e.hire_date < '2023-06-01' THEN 'Pleno Experiente'
WHEN e.salary >= 8000 THEN 'Funcionário Pleno'
ELSE 'Funcionário Júnior'
END AS tag_funcionario
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
ORDER BY e.salary DESC;
Saída:
nome | departamento | salary | tag_funcionario
----------+-------------+-----------+----------------------------
ZhangWei | Technology | 12000.00 | Equipe Técnica Principal
ZhaoMin | Sales | 11000.00 | Funcionário Sênior
LiNa | Technology | 9500.00 | Pleno Experiente
ChenJing | NULL | 9000.00 | Funcionário Pleno
WangQiang | Sales | 8000.00 | Pleno Experiente
LiuYang | Marketing | 7500.00 | Funcionário Júnior
(2) Cenário 2: UPDATE + CASE para Atualizações Condicionais em Lote
-- Ajustar salário com base no tempo de serviço e departamento
UPDATE employees
SET salary = CASE
WHEN department_id = 1 AND hire_date < '2023-01-01' THEN salary * 1.15
WHEN department_id = 1 THEN salary * 1.10
WHEN department_id = 2 THEN salary * 1.08
WHEN department_id IS NULL THEN salary * 1.05
ELSE salary * 1.03
END;
❓ Perguntas Frequentes
P: Qual a diferença entre CASE WHEN e IF? Qual devo usar? R:
IFsó pode lidar com escolhas binárias (verdadeiro/falso) e é adequado para cenários simples;CASE WHENpode lidar com múltiplos ramos de condições e é adequado para lógica complexa. No MySQL,IFé mais conciso, masCASE WHENé o padrão SQL com melhor compatibilidade entre bancos de dados. Para condições complexas, use CASE; para verificações simples, use IF ou COALESCE.
P: Expressões CASE podem ser usadas em cláusulas WHERE? R: Sim, mas não é recomendado. Condições devem ser escritas diretamente no WHERE em vez de envolvidas em CASE. CASE é mais adequado para gerar novas colunas no SELECT, ordenação personalizada no ORDER BY e agregação condicional no GROUP BY.
P: Qual é a ordem de execução do CASE WHEN? R: CASE avalia cláusulas WHEN na ordem escrita — uma vez que uma condição WHEN é verdadeira, retorna o valor THEN correspondente e os WHENs subsequentes não são avaliados. Coloque as condições mais comuns ou de maior prioridade primeiro.
P: Qual é melhor, COALESCE ou IFNULL? R:
COALESCEé uma função padrão SQL que suporta múltiplos argumentos (ex:COALESCE(a, b, c, 0)) e funciona entre bancos de dados;IFNULLé específica do MySQL e suporta apenas dois argumentos.COALESCEé recomendada para melhor compatibilidade e flexibilidade.
📖 Resumo
CASE WHENé a expressão condicional do SQL e pode aparecer em SELECT, WHERE, ORDER BY, GROUP BY e mais- Simple CASE: comparação de igualdade, adequado para "um campo correspondendo a múltiplos valores"
- Searched CASE: condições arbitrárias, adequado para lógica complexa, recomendado como escolha padrão
- CASE no GROUP BY: combinado com SUM/COUNT para estatísticas condicionais (pivô de linhas para colunas), uma técnica central de análise de dados
- CASE no UPDATE: completa múltiplas operações de atualização em um único UPDATE
- IF/IFNULL/COALESCE: funções condicionais mais concisas; COALESCE tem a melhor compatibilidade
📝 Exercícios
Exercício 1 (⭐): Consulte todos os pedidos, adicionando uma coluna "faixa de valor": valor >= 3000 é "Pedido Grande", 1000-2999 é "Pedido Médio", < 1000 é "Pedido Pequeno". Ordene por faixa de valor.
Exercício 2 (⭐⭐): Agregue estatísticas de pedidos por funcionário usando CASE WHEN com funções de agregação para gerar um relatório com: nome do funcionário, total de pedidos, pedidos concluídos, pedidos pendentes e total de vendas.
Exercício 3 (⭐⭐): Use UPDATE + CASE para aumentar o salário em 10% para funcionários do departamento "Sales", 8% para o departamento "Technology", e 5% para outros departamentos.
4. Próxima Lição
👉 17-views-indexes - Visualizações e Índices: Aprenda como criar e usar visualizações (tabelas virtuais), bem como conceitos de índices e estratégias de otimização!