SQL para análise de dados · Guias · 30 de outubro de 2026 · 12 min de leitura
SQL ou Excel para análise de dados: quando usar cada um e como migrar

Excel e SQL são menos concorrentes e mais ferramentas para etapas diferentes do mesmo trabalho. O SQL é melhor para buscar, juntar e resumir dados: funciona com milhões de linhas, lê os dados direto de onde eles estão, e uma consulta é o registro escrito exato do que você fez, que dá para executar de novo amanhã. O Excel é melhor para olhar, ajustar e apresentar um resultado pequeno: modelos de cenário, gráficos rápidos, correções manuais e um arquivo que qualquer pessoa da empresa consegue abrir. A maioria dos analistas usa os dois todos os dias: o SQL para produzir uma tabela de algumas centenas de linhas, o Excel ou uma ferramenta de BI para trabalhar com ela.
Se você já sabe Excel, sabe mais SQL do que imagina. Uma tabela dinâmica é um GROUP BY. O PROCV é um JOIN. Um filtro é um WHERE. Este guia traduz os hábitos que você já tem no Excel para o SQL, com consultas que rodam no banco de dados da companhia aérea do curso de SQL da Nomto (104 aeroportos, 33.121 voos, 262.788 reservas, valores em dólares americanos). Cada tabela de resultado abaixo é a saída real. As fórmulas do Excel aparecem com os nomes da versão em português (PROCV, SE, SOMASES) e com ; como separador.
A resposta curta: quando usar cada um
| Tarefa | Melhor no | Por quê |
|---|---|---|
| Puxar dados do banco de dados da empresa | SQL | os dados estão lá; exportar é um passo manual que fica desatualizado |
| Mais de cerca de um milhão de linhas | SQL | uma planilha do Excel comporta no máximo 1.048.576 linhas |
| Juntar várias tabelas | SQL | um JOIN em vez de uma coluna de PROCV por tabela |
| Um relatório que você refaz toda semana | SQL | executa a consulta de novo; não há passos de copiar e colar para esquecer |
| Conferir como um número foi calculado | SQL | a consulta é a receita completa |
| Cenários e modelos financeiros | Excel | muda uma célula e vê todos os números dependentes se atualizarem |
| Uma olhada rápida num arquivo pequeno | Excel | abre, ordena, olha, pronto |
| Edições manuais, notas, cores | Excel | o SQL não deixa você digitar dentro do resultado |
| Gráficos para uma reunião em cinco minutos | Excel | já vem pronto e todo mundo conhece |
| Compartilhar com quem não programa | Excel | todo mundo tem e consegue abrir |
Uma regra útil: se o trabalho é “achar, combinar e contar”, comece no SQL. Se o trabalho é “mexer nessa tabela e mostrar para alguém”, o Excel serve, e muitas vezes é melhor.
Por que o limite de linhas importa mais do que parece
Neste banco do curso, ticket_flights (uma linha por passageiro por trecho de voo) tem 1.045.726 linhas, que mal cabem numa planilha. A tabela de eventos do aplicativo não cabe de jeito nenhum:
SELECT COUNT(*) FROM app_events;
| count_star() |
|---|
| 1494723 |
E caber não é o mesmo que trabalhar com conforto: uma pasta de trabalho com um milhão de linhas de PROCV e fórmulas recalcula devagar. No SQL, o tamanho da tabela quase não muda o jeito de escrever a consulta.
Filtros → WHERE
No Excel você clica na seta do filtro e marca os valores. No SQL você escreve a condição. Reservas feitas a partir de agosto com valor de US$ 1.000 ou mais, e quanto elas somam:
SELECT COUNT(*) AS bookings, SUM(total_amount) AS revenue
FROM bookings
WHERE book_date >= '2026-08-01'
AND total_amount >= 1000;
| bookings | revenue |
|---|---|
| 16081 | 29341684.00 |
As equivalências:
| Filtro do Excel | SQL |
|---|---|
| marcar “Arrived” e “Departed” | WHERE status IN ('Arrived', 'Departed') |
| Filtros de número: é maior ou igual a | WHERE total_amount >= 1000 |
| Filtros de texto: começa com | WHERE city LIKE 'Novo%' |
| Filtros de data: entre | WHERE book_date >= '2026-08-01' AND book_date < '2026-09-01' |
| (Vazias) | WHERE actual_departure IS NULL |
Uma diferença pega quem vem do Excel: no SQL, uma célula vazia é NULL, e = NULL nunca encontra nada. Use IS NULL.
Classificar e “10 primeiros” → ORDER BY e LIMIT
“Classificar do maior para o menor e olhar os cinco primeiros” é:
SELECT book_ref, book_date, total_amount
FROM bookings
ORDER BY total_amount DESC
LIMIT 5;
No Excel, classificar muda a planilha. No SQL, muda só este resultado; a tabela continua como estava.
PROCV / PROCX → JOIN
Em flights, aeroportos e aviões aparecem só como códigos. No Excel você acrescentaria três colunas de PROCV, cada uma apontando para outra aba. No SQL são três JOIN numa consulta:
SELECT f.flight_no,
f.scheduled_departure,
dep.city AS from_city,
arr.city AS to_city,
a.model
FROM flights f
JOIN airports dep ON dep.airport_code = f.departure_airport
JOIN airports arr ON arr.airport_code = f.arrival_airport
JOIN aircrafts a ON a.aircraft_code = f.aircraft_code
WHERE f.departure_airport = 'SVO'
AND f.scheduled_departure >= '2026-08-01'
AND f.scheduled_departure < '2026-08-02'
ORDER BY f.scheduled_departure, f.flight_no
LIMIT 4;
| flight_no | scheduled_departure | from_city | to_city | model |
|---|---|---|---|---|
| PG0120 | 2026-08-01 09:00:00 | Moscow | Mirny | Boeing 737-300 |
| PG0591 | 2026-08-01 09:00:00 | Moscow | Tomsk | Sukhoi Superjet-100 |
| PG0241 | 2026-08-01 09:40:00 | Moscow | Cheboksary | Sukhoi Superjet-100 |
| PG0677 | 2026-08-01 09:40:00 | Moscow | Makhachkala | Boeing 737-300 |
Repare que a mesma tabela airports entra duas vezes, uma para cada ponta do voo, com aliases diferentes. No Excel seriam dois PROCV separados na mesma aba.
Dois comportamentos são diferentes do PROCV, e os dois importam:
Sem correspondência. O PROCV mostra #N/D. Um JOIN interno descarta a linha em silêncio. Se você quer mantê-la com o valor vazio, use LEFT JOIN. Aqui está o único modelo de avião sem voos, que um JOIN interno esconderia:
SELECT a.model
FROM aircrafts a
LEFT JOIN flights f ON f.aircraft_code = a.aircraft_code
WHERE f.flight_id IS NULL;
| model |
|---|
| Airbus A320-200 |
Várias correspondências. O PROCV devolve a primeira e ignora o resto. Um JOIN devolve todas, repetindo a linha uma vez para cada uma. Uma reserva pode ter até cinco bilhetes:
SELECT b.book_ref, b.total_amount, COUNT(t.ticket_no) AS tickets
FROM bookings b
JOIN tickets t ON t.book_ref = b.book_ref
GROUP BY b.book_ref, b.total_amount
ORDER BY tickets DESC, b.book_ref
LIMIT 3;
| book_ref | total_amount | tickets |
|---|---|---|
| 070133 | 1133.00 | 5 |
| 070682 | 8012.00 | 5 |
| 111C34 | 2120.00 | 5 |
Então, se você junta reservas com bilhetes e depois soma total_amount, cada reserva é contada uma vez por bilhete:
SELECT (SELECT SUM(total_amount) FROM bookings) AS correct,
SUM(b.total_amount) AS after_join
FROM bookings b
JOIN tickets t ON t.book_ref = b.book_ref;
| correct | after_join |
|---|---|
| 207669809.00 | 343206192.00 |
Esse é o erro de SQL mais comum de quem vem do Excel, porque o PROCV nunca multiplica linhas. Antes de um JOIN, pergunte: para uma linha da esquerda, quantas linhas podem corresponder na direita? O guia de JOIN no SQL explica isso em detalhe.
Tabela dinâmica → GROUP BY
Área de Linhas = colunas do GROUP BY. Área de Valores = agregações. Receita por classe de cabine, com a fatia de cada classe no total (na tabela dinâmica: “Mostrar valores como % do total geral”):
SELECT fare_conditions,
COUNT(*) AS segments,
SUM(amount) AS revenue,
ROUND(100.0 * SUM(amount) / SUM(SUM(amount)) OVER (), 1) AS pct_of_revenue
FROM ticket_flights
GROUP BY fare_conditions
ORDER BY revenue DESC;
| fare_conditions | segments | revenue | pct_of_revenue |
|---|---|---|---|
| Economy | 920793 | 146956844.00 | 70.8 |
| Business | 107642 | 55051796.00 | 26.5 |
| Comfort | 17291 | 5661169.00 | 2.7 |
Isso rodou sobre mais de um milhão de linhas. SUM(SUM(amount)) OVER () é uma função de janela que coloca o total geral ao lado de cada grupo; funções de janela SQL explica como.
Uma tabela dinâmica com a área de Colunas (status nas linhas, meses nas colunas) é uma contagem condicional por coluna:
SELECT status,
COUNT(*) FILTER (WHERE EXTRACT(MONTH FROM scheduled_departure) = 7) AS jul,
COUNT(*) FILTER (WHERE EXTRACT(MONTH FROM scheduled_departure) = 8) AS aug,
COUNT(*) FILTER (WHERE EXTRACT(MONTH FROM scheduled_departure) = 9) AS sep,
COUNT(*) AS total
FROM flights
GROUP BY status
ORDER BY total DESC;
| status | jul | aug | sep | total |
|---|---|---|---|---|
| Arrived | 10821 | 5886 | 0 | 16707 |
| Scheduled | 0 | 10345 | 5038 | 15383 |
| On Time | 0 | 518 | 0 | 518 |
| Cancelled | 5 | 6 | 403 | 414 |
| Departed | 0 | 58 | 0 | 58 |
| Delayed | 0 | 41 | 0 | 41 |
Aqui o Excel é, honestamente, mais prático: a tabela dinâmica monta as colunas para você, enquanto no SQL você precisa listá-las. Muitos analistas fazem exatamente essa divisão: o SQL produz a tabela longa (status, mês, contagem) e a tabela dinâmica no Excel ou na ferramenta de BI a abre em colunas.
A área de Filtros da tabela dinâmica é o WHERE (antes do agrupamento), e “mostrar só os grupos cujo total passa de N” é o HAVING. Veja GROUP BY e HAVING.
Fórmulas → expressões
| Excel | SQL |
|---|---|
=A2*B2, =ARRED(A2; 2) |
price * qty, ROUND(amount, 2) no SELECT |
=SE(A2>=1000; "large"; "small") |
CASE WHEN total_amount >= 1000 THEN 'large' ELSE 'small' END |
=SEERRO(A2/B2; "") |
a / NULLIF(b, 0) |
=CONT.SE(intervalo; "Cancelled") |
COUNT(*) FILTER (WHERE status = 'Cancelled') |
=SOMASES(valor; classe; "Business") |
SUM(amount) FILTER (WHERE fare_conditions = 'Business') |
=A2 & " " & B2 |
a || ' ' || b |
=ESQUERDA(A2; 3), =MAIÚSCULA(A2), =ARRUMAR(A2) |
LEFT(s, 3), UPPER(s), TRIM(s) |
=FIMMÊS, =ANO, =A2-B2 com datas |
DATE_TRUNC, EXTRACT(YEAR FROM d), d1 - d2 |
| Remover Duplicatas | SELECT DISTINCT / COUNT(DISTINCT col) |
uma coluna de total acumulado =C1+B2 |
SUM(x) OVER (ORDER BY day) |
A maior mudança de mentalidade: uma fórmula do Excel mora numa célula e você a arrasta para baixo. Uma expressão SQL é escrita uma vez e vale para todas as linhas. Os SE aninhados viram um CASE, que se lê de cima para baixo:
SELECT book_ref, total_amount,
CASE WHEN total_amount >= 1000 THEN 'large'
WHEN total_amount >= 300 THEN 'medium'
ELSE 'small'
END AS size
FROM bookings
ORDER BY book_ref
LIMIT 4;
| book_ref | total_amount | size |
|---|---|---|
| 00000F | 2657.00 | large |
| 000012 | 379.00 | medium |
| 000068 | 181.00 | small |
| 000181 | 1318.00 | large |
E a coluna que você acrescentaria ao lado para depois montar a tabela dinâmica é só mais um GROUP BY:
SELECT CASE WHEN total_amount >= 1000 THEN 'large'
WHEN total_amount >= 300 THEN 'medium'
ELSE 'small'
END AS size,
COUNT(*) AS bookings
FROM bookings
GROUP BY size
ORDER BY bookings DESC;
| size | bookings |
|---|---|
| medium | 130009 |
| small | 68305 |
| large | 64474 |
Remover Duplicatas, por exemplo quantas cidades distintas têm aeroporto:
SELECT COUNT(*) AS airports, COUNT(DISTINCT city) AS cities
FROM airports;
| airports | cities |
|---|---|
| 104 | 101 |
Onde o Excel ganha de verdade
Vale ser honesto sobre isso, porque “o SQL é melhor” não é verdade para tudo:
- Modelagem. Um orçamento, uma previsão ou um cenário de preços em que você muda uma premissa e vê o resto se mexer é exatamente o que as planilhas foram feitas para fazer. O SQL não tem células para mudar.
- Dados pequenos, bagunçados e pontuais. Uma lista que alguém mandou por e-mail, com células mescladas e anotações na margem, é mais rápida de limpar na mão do que de carregar num banco.
- Entrada manual. Acrescentar um comentário, corrigir um valor, colorir as linhas que você quer discutir.
- Comunicação. Seu gestor consegue abrir uma pasta de trabalho. A maioria não consegue abrir uma consulta.
- Power Query e o Modelo de Dados. O Excel moderno consegue carregar e juntar mais dados do que cabem numa planilha. Se a sua empresa vive no Excel, esses recursos fecham parte da distância, embora a lógica continue mais difícil de revisar do que uma consulta.
O que o SQL dá em troca é reprodutibilidade. Uma planilha que passou por vinte passos manuais não é fácil de conferir nem de refazer; uma consulta pode ser lida linha por linha, executada de novo nos dados do mês seguinte e revisada por um colega.
Como migrar: um caminho prático
- Aprenda a ler uma linha. Antes de cada consulta, saiba o que uma linha de cada tabela significa (um voo, uma reserva, um trecho de bilhete). Isso substitui o hábito de rolar a planilha.
- Comece pelo que você já faz no Excel. Filtro →
WHERE, classificar →ORDER BY, tabela dinâmica →GROUP BY. Refaça em SQL um dos seus relatórios semanais reais. - Depois, os
JOIN. Substitua seus PROCV e confira a contagem de linhas antes e depois de cadaJOIN. - Deixe o Excel para o último passo. Exporte o resultado final, pequeno, para uma planilha para gráficos e comentários. Isso não é trapaça; é como a maioria dos analistas trabalha.
- Acrescente
CASE, CTE e funções de janela quando o básico virar rotina. A cola de SQL tem todos eles numa página.
Na sala de SQL da Nomto você executa essas consultas no navegador, no banco da companhia aérea, sem instalar nada, e o curso começa exatamente pelas operações parecidas com as do Excel: selecionar colunas, filtrar, ordenar e agrupar. O guia de comandos SQL básicos é uma boa primeira leitura.
Perguntas frequentes
SQL é mais difícil de aprender que Excel?
O básico não é. Se você sabe montar uma tabela dinâmica e usar o PROCV, consegue aprender SELECT, WHERE, GROUP BY e JOIN em poucas semanas. O que exige prática é pensar em tabelas inteiras em vez de células soltas, e perceber quando um JOIN multiplica linhas.
O SQL pode substituir o Excel completamente?
Para buscar e resumir dados, quase sempre sim. Para modelagem, edições manuais e apresentação rápida, não. A maioria dos analistas usa o SQL para produzir um resultado pequeno e uma planilha ou ferramenta de BI para trabalhar com ele.
Analistas de dados ainda usam Excel?
Sim, bastante, principalmente no último passo de uma análise e para compartilhar resultados. O SQL é o que busca os dados; Excel, Google Planilhas ou uma ferramenta de BI muitas vezes é o que as pessoas veem.
Qual é o equivalente do PROCV no SQL?
Um JOIN pela coluna de busca: FROM flights f JOIN aircrafts a ON a.aircraft_code = f.aircraft_code. Use LEFT JOIN se quiser manter as linhas sem correspondência, do jeito que o PROCV mantém a linha e mostra #N/D.
Outros idiomas: English, Español, Tiếng Việt, 简体中文