Módulo 2: NULL e filtros finos
IS NULL, COALESCE, CASE
Teoria
NULL= "sem valor". Não é 0 nem''. Não dá pra comparar com=: useIS NULL/IS NOT NULL.- Qualquer conta com
NULLviraNULL(10 + NULL=NULL). COALESCE(a, b, c): devolve o primeiro argumento que não forNULL.CASE WHEN condição THEN x WHEN ... THEN y ELSE z END: o "if" dentro doSELECT. Bom pra criar faixas/rótulos.- Truque útil:
SUM(CASE WHEN cond THEN 1 ELSE 0 END)conta quantas linhas batem uma condição.
Olhar de QA: linha com data_fechamento IS NULL = defeito ainda aberto. NULL onde não devia é uma classe inteira de bug.
Exemplos de aplicação
Um exemplo montado pra cada item da teoria acima. Não precisa rodar: é pra ver a cara do recurso e entender cada pedaço. Os valores são ilustrativos.
IS NULL / IS NOT NULL
SELECT id, titulo, data_fechamento
FROM defeitos
WHERE data_fechamento IS NULL;
data_fechamento tem a data em que o defeito foi fechado, ou NULL se ainda está aberto. WHERE data_fechamento = NULL nunca dá certo (não dá pra comparar com =); o teste é IS NULL. Essa query lista os defeitos em aberto.
Conta com NULL vira NULL
SELECT id,
data_fechamento,
julianday(data_fechamento) - julianday(data_abertura) AS dias_aberto
FROM defeitos;
Nos defeitos fechados, dias_aberto vem com o número. Nos que têm data_fechamento nulo, a subtração inteira vira NULL, porque qualquer operação que toca em NULL resulta NULL. É por isso que linhas assim "somem" de médias e somas sem dar erro.
COALESCE(a, b, ...)
SELECT id,
COALESCE(data_fechamento, 'ainda aberto') AS situacao
FROM defeitos;
COALESCE devolve o primeiro argumento que não for NULL. Aqui: se tem data_fechamento, mostra a data; se é NULL, mostra o texto 'ainda aberto'. Útil pra não deixar célula vazia em relatório.
CASE WHEN ... THEN ... END
SELECT nome,
preco,
CASE
WHEN preco < 100 THEN 'barato'
WHEN preco < 500 THEN 'medio'
ELSE 'caro'
END AS faixa_preco
FROM produtos;
É o "if" dentro do SELECT. Testa cada WHEN de cima pra baixo e para no primeiro verdadeiro; se nenhum bate, usa o ELSE. Cria a coluna faixa_preco com o rótulo. Sempre fecha com END.
SUM(CASE WHEN cond THEN 1 ELSE 0 END)
SELECT
COUNT(*) AS total,
SUM(CASE WHEN severidade = 'critica' THEN 1 ELSE 0 END) AS criticos,
SUM(CASE WHEN status = 'aberto' THEN 1 ELSE 0 END) AS em_aberto
FROM defeitos;
O CASE vira 1 quando a condição bate e 0 quando não. Somando esses valores você conta quantas linhas satisfazem cada condição, tudo numa passada. Resultado: uma linha com total, quantos são críticos e quantos estão abertos.
Pegadinhas deste módulo
Os erros que quase todo mundo comete aqui. Ler agora poupa meia hora de confusão depois, e alguns deles são a causa de relatório errado em projeto real.
NULLnão é igual a nada, nem a outroNULL.WHERE data_fechamento = NULLdevolve zero linhas sempre, mesmo havendo milhares com o campo vazio. O certo éIS NULL. Não dá erro: dá resultado vazio, que é pior.<>descarta as linhas comNULLem silêncio.WHERE status <> 'fechado'não traz as linhas cujo status éNULL, porqueNULL <> 'fechado'não é verdadeiro, é desconhecido. Se você quer essas linhas, precisa deOR status IS NULL. Esta é uma das maiores fontes de relatório com número errado.- Qualquer conta com
NULLviraNULL.valor_total + fretesome se o frete for nulo. UseCOALESCE(frete, 0)quando o vazio deve valer zero. NULL, string vazia e zero são três coisas diferentes.NULL= nunca preenchido;''= preenchido com nada;0= preenchido com zero. Tratar os três como "vazio" no teste é como defeito de importação de dados passa despercebido.CASEsemELSEdevolveNULL. Se nenhuma condição bater e não houverELSE, o resultado é nulo, e a soma daquela coluna some junto.
Prática
Rode com o botão ou Ctrl+Enter.
carregando banco…