Guia para Evoluir de Júnior para Pleno em SQL
Para evoluir de um nível júnior para um nível pleno em SQL, é necessário desenvolver habilidades técnicas, práticas e conceituais, além de ganhar experiência em cenários reais. Abaixo está um guia com os principais pontos que você deve dominar ou aprimorar, dividido em categorias claras: Este guia é destinado a profissionais que já possuem uma base em SQL e desejam avançar para um nível pleno. O objetivo é fornecer um caminho claro e estruturado para aprimorar suas habilidades, cobrindo desde fundamentos até conceitos avançados, além de práticas recomendadas e exercícios práticos.
Objetivos
- Dominar SQL: Aprender a escrever queries complexas, otimizar performance e entender conceitos avançados.
- Modelagem de dados: Compreender como estruturar bancos de dados de forma eficiente.
- Otimização de performance: Aprender a analisar e melhorar o desempenho de queries.
- Integração com outras ferramentas: Conectar SQL com linguagens de programação e ferramentas de BI.
- Experiência prática: Aplicar conhecimentos em projetos reais ou simulados.
Como Praticar os Exercícios
-
Datasets sugeridos:
- Kaggle: E-commerce Sales Dataset, Retail Sales Dataset.
- Google BigQuery: Datasets públicos como google_analytics_sample.
- Bancos de exemplo: Northwind, AdventureWorks, Sakila.
-
Ferramentas:
- Bancos: MySQL, PostgreSQL, SQLite (para testes locais).
- IDEs: DBeaver, pgAdmin, SQL Server Management Studio.
- Plataformas online: SQLFiddle, DB Fiddle, LeetCode.
-
Portfólio: Documente seus exercícios em um repositório no GitHub com o código SQL, explicações e resultados (ex.: capturas de tela ou CSVs).
Dicas para os Exercícios
- Comece simples: Foque nos exercícios 1 e 2 para reforçar fundamentos.
- Progrida gradualmente: Passe para exercícios avançados (3, 4, 6) à medida que ganhar confiança.
- Peça feedback: Compartilhe suas queries em fóruns (ex.: Stack Overflow) ou com colegas sêniores.
- Simule cenários reais: Tente replicar relatórios ou problemas do seu trabalho atual.
- Documente seu aprendizado: Mantenha um diário de aprendizado com as queries que você escreveu, os problemas que resolveu e as lições aprendidas.
1. Fundamentos Sólidos em SQL
-
Domínio das operações básicas:
-
SELECT, INSERT, UPDATE, DELETE: Entenda como manipular dados com precisão, incluindo filtros (
WHERE), ordenação (ORDER BY) e agrupamento (GROUP BY). -
Joins: Domine
INNER JOIN,LEFT JOIN,RIGHT JOIN,FULL JOINeCROSS JOIN. Saiba quando usar cada um e como otimizar queries com múltiplos joins.
-
Funções agregadas:
COUNT,SUM,AVG,MIN,MAX, e como combiná-las comGROUP BYeHAVING.- COUNT: Conta o número de linhas.
SELECT COUNT(*) FROM vendas; - SUM: Soma valores.
SELECT vendedor, SUM(valor) AS valor_total FROM vendas GROUP BY vendedor HAVING SUM(valor) > 1000; - AVG: Calcula a média.
SELECT AVG(preco) AS preco_medio FROM produtos; - MIN e MAX: Encontram o menor e maior valor, respectivamente.
SELECT MIN(preco) AS preco_minimo, MAX(preco) AS preco_maximo FROM produtos;
- COUNT: Conta o número de linhas.
-
GROUP BY: Agrupa resultados para aplicar funções agregadas.
- HAVING: Filtra grupos após a agregação, diferentemente do
WHERE, que filtra antes da agregação. - Exemplo de uso de GROUP BY e HAVING:
SELECT vendedor, SUM(valor) AS valor_total FROM vendas GROUP BY vendedor HAVING SUM(valor) > 1000;- Explicação:
- FROM vendas: Seleciona a tabela de vendas.
- GROUP BY vendedor: Agrupa os resultados por vendedor.
- HAVING SUM(valor) > 1000: Filtra os grupos onde a soma dos valores de vendas é maior que 1000.
- SELECT vendedor, SUM(valor) AS valor_total: Exibe o vendedor e o total de vendas.
- HAVING: Filtra grupos após a agregação, diferentemente do
-
WHERE vs HAVING: Entenda a diferença entre os dois.
- WHERE: Filtra linhas antes da agregação.
SELECT vendedor, SUM(valor) AS valor_total FROM vendas WHERE data_venda >= '2025-01-01' GROUP BY vendedor;- Explicação:
- FROM vendas: Seleciona a tabela de vendas.
- WHERE data_venda >= '2025-01-01': Filtra as vendas a partir de 1º de janeiro de 2025.
- GROUP BY vendedor: Agrupa os resultados por vendedor.
- SELECT vendedor, SUM(valor) AS valor_total: Exibe o vendedor e o total de vendas.
- HAVING: Filtra grupos após a agregação.
SELECT vendedor, SUM(valor) AS valor_total FROM vendas GROUP BY vendedor HAVING SUM(valor) > 1000;- Explicação:
- FROM vendas: Seleciona a tabela de vendas.
- GROUP BY vendedor: Agrupa os resultados por vendedor.
- HAVING SUM(valor) > 1000: Filtra os grupos onde a soma dos valores de vendas é maior que 1000.
- SELECT vendedor, SUM(valor) AS valor_total: Exibe o vendedor e o total de vendas.
- WHERE: Filtra linhas antes da agregação.
Exercício 1: Filtros e Agregações
- Objetivo: Criar uma query que resuma vendas por categoria de produto em um período específico.
- Tarefa: Usando uma tabela de vendas (
order_id,product_id,category,order_date,amount), escreva uma query que:- Filtre pedidos de 2024.
- Agrupe por categoria de produto.
- Calcule o total de vendas (
SUM(amount)) e a quantidade de pedidos (COUNT(order_id)). - Ordene por total de vendas em ordem decrescente.
- Dica: Use
GROUP BY,WHEREeORDER BY. Teste com um dataset como o do Kaggle (ex.: "Retail Sales Dataset"). - Extra: Adicione uma condição com
HAVINGpara mostrar apenas categorias com mais de 100 pedidos.
Exercício 2: Joins Complexos
- Objetivo: Combinar múltiplas tabelas para obter informações detalhadas.
- Tarefa: Em um banco com tabelas
customers,orderseproducts, escreva uma query que:- Liste todos os clientes, mesmo aqueles sem pedidos (usando
LEFT JOIN). - Inclua o nome do produto de cada pedido.
- Mostre o total gasto por cliente.
- Liste todos os clientes, mesmo aqueles sem pedidos (usando
- Dica: Use
LEFT JOINentrecustomerseorders, eINNER JOINentreorderseproducts. Trate valores nulos comCOALESCEpara o total gasto. - Extra: Adicione uma coluna que indique se o cliente é "ativo" (fez pedidos nos últimos 6 meses).
-
-
Manipulação de strings: Use funções como
CONCAT,SUBSTRING,TRIM,UPPER,LOWEReREPLACEpara manipular dados textuais.- CONCAT: Junta strings.
SELECT CONCAT(nome, ' ', sobrenome) AS nome_completo FROM clientes; - SUBSTRING: Extrai parte de uma string.
SELECT SUBSTRING(nome, 1, 5) AS nome_curto FROM clientes; - TRIM: Remove espaços em branco do início e do fim de uma string.
SELECT TRIM(nome) AS nome_limpo FROM clientes; - UPPER: Converte uma string para maiúsculas.
SELECT UPPER(nome) AS nome_maiusculo FROM clientes; - LOWER: Converte uma string para minúsculas.
SELECT LOWER(nome) AS nome_minusculo FROM clientes; - REPLACE: Substitui parte de uma string por outra.
SELECT REPLACE(nome, 'Antigo', 'Novo') AS nome_atualizado FROM clientes;
- CONCAT: Junta strings.
-
Data e hora: Trabalhe com tipos de dados de data e hora, usando funções como
NOW(),DATEADD,DATEDIFF,FORMATeEXTRACT.- NOW(): Retorna a data e hora atuais.
SELECT NOW() AS data_atual; - DATEADD: Adiciona um intervalo a uma data.
SELECT DATEADD(DAY, 7, data_venda) AS data_futura FROM vendas; - DATEDIFF: Calcula a diferença entre duas datas.
SELECT DATEDIFF(DAY, data_inicio, data_fim) AS dias_diferenca FROM projetos; - FORMAT: Formata uma data em um formato específico.
SELECT FORMAT(data_venda, 'dd/MM/yyyy') AS data_formatada FROM vendas; - EXTRACT: Extrai partes de uma data (ano, mês, dia, etc.).
SELECT EXTRACT(YEAR FROM data_venda) AS ano_venda FROM vendas;
- NOW(): Retorna a data e hora atuais.
-
Tratamento de nulos: Use
IS NULL,IS NOT NULLpara lidar com valores nulos.- IS NULL: Verifica se um valor é nulo.
SELECT nome FROM clientes WHERE email IS NULL; - IS NOT NULL: Verifica se um valor não é nulo.
SELECT nome FROM clientes WHERE email IS NOT NULL;
- IS NULL: Verifica se um valor é nulo.
-
Filtros avançados: Use
CASE,COALESCEeNULLIFpara manipulação de dados e tratamento de valores nulos.-
CASE: Permite criar condições dentro de uma query, semelhante a um
ifem outras linguagens.SELECT produto, CASE WHEN categoria = 'Eletrônicos' THEN 'Tecnologia' WHEN categoria = 'Roupas' THEN 'Moda' ELSE 'Outros' END AS categoria_modificada FROM produtos;- COALESCE: Retorna o primeiro valor não nulo em uma lista de expressões.
SELECT nome, COALESCE(email, 'sem email') AS email_contato FROM clientes;- NULLIF: Retorna
NULLse os dois valores forem iguais, caso contrário, retorna o primeiro valor.
SELECT produto, NULLIF(preco, 0) AS preco_unitario FROM produtos;
-
-
Operadores: Domine operadores lógicos (
AND,OR,NOT), de comparação (=,<>,<,>,<=,>=) e de conjunto (IN,BETWEEN,LIKE).-
Operadores lógicos:
-
AND: Combina condições, retornando resultados que atendem a todas as condições.
SELECT nome FROM clientes WHERE idade > 18 AND cidade = 'São Paulo'; -
OR: Retorna resultados que atendem a pelo menos uma das condições.
SELECT nome FROM clientes WHERE cidade = 'São Paulo' OR cidade = 'Rio de Janeiro'; -
NOT: Inverte a condição, retornando resultados que não atendem à condição especificada.
SELECT nome FROM clientes WHERE NOT cidade = 'São Paulo';
-
-
Operadores de comparação:
-
=: Igualdade.
SELECT nome FROM clientes WHERE idade = 30; -
<>: Diferença.SELECT nome FROM clientes WHERE idade <> 30; -
<,>,<=,>=: Comparações numéricas.SELECT nome FROM clientes WHERE idade > 18;
-
-
Operadores de conjunto:
-
BETWEEN: Verifica se um valor está dentro de um intervalo.
SELECT nome FROM clientes WHERE idade BETWEEN 18 AND 30; -
BETWEEN também pode ser usado com datas:
SELECT nome FROM clientes WHERE data_cadastro BETWEEN '2024-01-01' AND '2024-12-31'; -
LIKE: Usado para busca de padrões em strings.
SELECT nome FROM clientes WHERE nome LIKE 'A%'; -
IN: Verifica se um valor está dentro de um conjunto.
SELECT produto FROM produtos WHERE categoria IN ('Eletrônicos', 'Roupas');
-
-
-
Subqueries: Escreva subqueries correlacionadas e não correlacionadas, entendendo a diferença entre elas.
-
Subquery simples: Retorna um único valor ou uma lista de valores.
SELECT nome FROM clientes WHERE id IN (SELECT cliente_id FROM pedidos WHERE valor > 100); -
Subquery correlacionada: Depende de uma coluna da query externa.
SELECT nome, (SELECT COUNT(*) FROM pedidos WHERE pedidos.cliente_id = clientes.id) AS total_pedidos FROM clientes;- Subquery não correlacionada: Não depende de nenhuma coluna da query externa.
SELECT nome FROM clientes WHERE id IN (SELECT cliente_id FROM pedidos WHERE valor > 100);
-
-
Índices e desempenho: Compreenda como índices (
CLUSTEREDeNON-CLUSTERED) funcionam e como afetam a performance de queries.- Índices: Índices são estruturas de dados que permitem acesso rápido a linhas em uma tabela. Eles melhoram a performance de consultas, mas podem impactar operações de escrita (inserções, atualizações, exclusões).
- CLUSTERED: Define a ordem física dos dados na tabela. Cada tabela pode ter apenas um índice clustered.
CREATE CLUSTERED INDEX idx_nome ON clientes(nome); - NON-CLUSTERED: Cria um índice separado da tabela, permitindo múltiplos índices non-clustered por tabela.
CREATE NONCLUSTERED INDEX idx_idade ON clientes(idade);
- CLUSTERED: Define a ordem física dos dados na tabela. Cada tabela pode ter apenas um índice clustered.
- Índices: Índices são estruturas de dados que permitem acesso rápido a linhas em uma tabela. Eles melhoram a performance de consultas, mas podem impactar operações de escrita (inserções, atualizações, exclusões).
Dica: Pratique escrevendo queries complexas e otimizando-as. Use plataformas como LeetCode, HackerRank ou SQLZoo.
2. Conceitos Avançados
-
Common Table Expressions (CTEs): Saiba usar CTEs para simplificar queries complexas e melhorar a legibilidade.
- CTE: Uma CTE é uma declaração que define uma tabela temporária que pode ser usada várias vezes em uma consulta.
-
Window Functions : Domine funções como
ROW_NUMBER,RANK,DENSE_RANK,PARTITION BYeOVERpara análises avançadas, como cálculos acumulados ou rankings.-
PARTITION BY: Divide os resultados em grupos para aplicar funções de janela.
SELECT nome, SUM(salario) OVER (PARTITION BY departamento) AS total_departamento FROM funcionarios;- Explicação:
- PARTITION BY departamento: Divide os resultados por departamento.
- SUM(salario) OVER (PARTITION BY departamento): Calcula o total de salários por departamento, aplicando a função de janela
SUMsobre cada partição.
-
OVER: Define a janela de dados sobre a qual a função de janela será aplicada.
SELECT nome, SUM(salario) OVER (ORDER BY data_contratacao) AS salario_acumulado FROM funcionarios;- Explicação:
- ORDER BY data_contratacao: Ordena os funcionários pela data de contratação.
- SUM(salario) OVER (ORDER BY data_contratacao): Calcula o salário acumulado ao longo do tempo, aplicando a função de janela
SUMsobre a janela definida pela ordenação.
-
ROW_NUMBER: Atribui um número sequencial a cada linha dentro de uma partição.
SELECT nome, ROW_NUMBER() OVER (PARTITION BY departamento ORDER BY salario DESC) AS ranking FROM funcionarios;- Explicação:
- PARTITION BY departamento: Divide os resultados por departamento.
- ORDER BY salario DESC: Ordena os funcionários por salário em ordem decrescente.
- ROW_NUMBER(): Atribui um número sequencial a cada funcionário dentro do seu departamento, começando do 1.
-
RANK: Atribui um ranking, permitindo empates.
SELECT nome, RANK() OVER (PARTITION BY departamento ORDER BY salario DESC) AS ranking FROM funcionarios;- Explicação:
- PARTITION BY departamento: Divide os resultados por departamento.
- ORDER BY salario DESC: Ordena os funcionários por salário em ordem decrescente.
- RANK(): Atribui um ranking a cada funcionário, permitindo empates. Se dois funcionários tiverem o mesmo salário, eles receberão o mesmo ranking, e o próximo ranking será pulado.
-
DENSE_RANK: Semelhante ao
RANK, mas não pula rankings em caso de empate.SELECT nome, DENSE_RANK() OVER (PARTITION BY departamento ORDER BY salario DESC) AS ranking FROM funcionarios;- Explicação:
- PARTITION BY departamento: Divide os resultados por departamento.
- ORDER BY salario DESC: Ordena os funcionários por salário em ordem decrescente.
- DENSE_RANK(): Atribui um ranking a cada funcionário, sem pular rankings em caso de empate. Se dois funcionários tiverem o mesmo salário, eles receberão o mesmo ranking, mas o próximo ranking será o próximo número sequencial.
Outras dicas sobre windows funcitions aqui
-
Exercício 3: Window Functions
- Objetivo: Calcular rankings e acumulados com funções de janela.
- Tarefa: Usando uma tabela de vendas (
order_id,customer_id,amount,order_date), escreva uma query que:- Atribua um ranking (
RANK) para cada cliente com base no total de vendas. - Calcule o total acumulado de vendas por cliente ao longo do tempo (
SUMcomOVER).
- Atribua um ranking (
- Dica: Use
PARTITION BY customer_ideORDER BY order_datepara o acumulado. Teste com PostgreSQL ou SQL Server, pois MySQL tem limitações em versões antigas. - Extra: Adicione uma coluna com a diferença entre o
amountdo pedido atual e o pedido anterior do mesmo cliente.
Exercício 4: CTEs para Queries Complexas
-
Objetivo: Simplificar uma query complexa usando CTEs.
-
Tarefa: Em um dataset de funcionários (
employee_id,department_id,salary,hire_date), escreva uma query que:- Use uma CTE para calcular o salário médio por departamento.
- Junte a CTE com a tabela original para listar funcionários com salário acima da média do seu departamento.
-
Dica: Crie a CTE com
SELECT department_id, AVG(salary) FROM employees GROUP BY department_id. -
Extra: Adicione uma segunda CTE para contar o número de funcionários por departamento e inclua essa informação na query final.
-
Observação: CTEs são úteis para evitar a necessidade de subconsultas complexas e melhorar a legibilidade do código.
-
Stored Procedures e Functions: Aprenda a criar e usar procedures e funções para encapsular lógica de negócio no banco.
- Stored Procedures: São blocos de código SQL que podem ser executados no banco de dados. Elas permitem encapsular lógica complexa e reutilizar código.
- Criação de uma Stored Procedure:
CREATE PROCEDURE calcular_bonus(IN funcionario_id INT) BEGIN DECLARE bonus DECIMAL(10,2); SELECT salario * 0.1 INTO bonus FROM funcionarios WHERE id = funcionario_id; UPDATE funcionarios SET bonus = bonus WHERE id = funcionario_id; END; - Execução de uma Stored Procedure:
CALL calcular_bonus(1);
- Criação de uma Stored Procedure:
- Stored Procedures: São blocos de código SQL que podem ser executados no banco de dados. Elas permitem encapsular lógica complexa e reutilizar código.
-
Triggers: Entenda como criar triggers para automatizar ações no banco, como auditoria ou validações.
- Triggers: São procedimentos que são automaticamente executados em resposta a eventos específicos no banco de dados, como inserções, atualizações ou exclusões.
- Criação de um Trigger:
CREATE TRIGGER antes_de_atualizar_salario BEFORE UPDATE ON funcionarios FOR EACH ROW BEGIN IF NEW.salario < 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Salário não pode ser negativo'; END IF; END; - Explicação:
- BEFORE UPDATE ON funcionarios: O trigger será executado antes de qualquer atualização na tabela
funcionarios. - FOR EACH ROW: O trigger será executado para cada linha afetada pela atualização.
- IF NEW.salario < 0 THEN: Verifica se o novo salário é negativo.
- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Salário não pode ser negativo';: Lança um erro se a condição for verdadeira, impedindo a atualização.
- BEFORE UPDATE ON funcionarios: O trigger será executado antes de qualquer atualização na tabela
- Criação de um Trigger:
- Tipos de Triggers:
- BEFORE: Executado antes de uma operação (INSERT, UPDATE, DELETE).
- AFTER: Executado após uma operação.
- INSTEAD OF: Executado no lugar de uma operação, útil para views.
- Exemplo de Trigger:
- Trigger de Auditoria: Registra alterações em uma tabela de auditoria.
CREATE TRIGGER auditoria_atualizacao AFTER UPDATE ON funcionarios FOR EACH ROW BEGIN INSERT INTO auditoria (funcionario_id, campo, valor_antigo, valor_novo, data) VALUES (NEW.id, 'salario', OLD.salario, NEW.salario, NOW()); END; - Explicação:
- AFTER UPDATE ON funcionarios: O trigger será executado após uma atualização na tabela
funcionarios. - FOR EACH ROW: O trigger será executado para cada linha afetada pela atualização.
- INSERT INTO auditoria: Insere um registro na tabela de auditoria com os detalhes da atualização.
- NEW.id, 'salario, OLD.salario, NEW.salario, NOW(): Captura o ID do funcionário, o campo alterado, o valor antigo, o novo valor e a data da alteração.
- AFTER UPDATE ON funcionarios: O trigger será executado após uma atualização na tabela
- Trigger de Auditoria: Registra alterações em uma tabela de auditoria.
- Dicas para Triggers:
- Evite lógica complexa: Mantenha os triggers simples para evitar problemas de performance e manutenção.
- Teste cuidadosamente: Triggers podem causar efeitos colaterais inesperados, então teste-os em um ambiente controlado antes de aplicá-los em produção.
- Triggers: São procedimentos que são automaticamente executados em resposta a eventos específicos no banco de dados, como inserções, atualizações ou exclusões.
-
Transações: Compreenda o uso de
BEGIN TRANSACTION,COMMITeROLLBACKpara garantir consistência de dados.- Transações: São conjuntos de operações que são executadas como um único bloco. Elas garantem que todas as operações sejam concluídas com sucesso ou nenhuma delas seja aplicada, mantendo a integridade dos dados.
- BEGIN TRANSACTION: Inicia uma nova transação.
BEGIN TRANSACTION; - COMMIT: Confirma todas as operações realizadas na transação, tornando-as permanentes.
COMMIT; - ROLLBACK: Desfaz todas as operações realizadas na transação, revertendo os dados ao estado anterior.
- Exemplo de uso de transações:
BEGIN TRANSACTION; UPDATE contas SET saldo = saldo - 100 WHERE id = 1; UPDATE contas SET saldo = saldo + 100 WHERE id = 2; IF @@ERROR <> 0 THEN ROLLBACK; ELSE COMMIT; END IF;
- BEGIN TRANSACTION: Inicia uma nova transação.
- Transações: São conjuntos de operações que são executadas como um único bloco. Elas garantem que todas as operações sejam concluídas com sucesso ou nenhuma delas seja aplicada, mantendo a integridade dos dados.
3. Modelagem de Dados
-
Normalização: Entenda as formas normais (1NF, 2NF, 3NF) e quando aplicá-las para evitar redundâncias.
- 1NF (Primeira Forma Normal): Cada atributo deve ser único e não deve conter valores repetidos. Tabelas devem ter uma chave primária.
- Exemplo: Uma tabela de clientes onde cada cliente tem um ID único, nome e email.
CREATE TABLE clientes ( cliente_id INT PRIMARY KEY, nome VARCHAR(100), email VARCHAR(100) ); - 2NF (Segunda Forma Normal): Cada atributo não-chave deve depender completamente da chave primária. Elimine dependências parciais.
- Exemplo: Uma tabela de pedidos onde cada pedido tem um ID único e um cliente associado, mas o nome do cliente não deve ser armazenado na tabela de pedidos, pois depende apenas do cliente.
CREATE TABLE pedidos ( pedido_id INT PRIMARY KEY, cliente_id INT, produto VARCHAR(100), quantidade INT, FOREIGN KEY (cliente_id) REFERENCES clientes(cliente_id) );- 3NF (Terceira Forma Normal): Se uma tabela estiver em 2NF, mas ainda tiver atributos que dependem de outros atributos não-chave, deve-se remover essas dependências transitivas.
- Exemplo: Uma tabela de pedidos onde cada pedido tem um ID único e um cliente associado, e o produto não deve conter informações adicionais que dependam de outro atributo, como categoria.
CREATE TABLE produtos ( produto_id INT PRIMARY KEY, nome VARCHAR(100), categoria VARCHAR(50) );- Exemplo de tabela normalizada:
CREATE TABLE clientes ( cliente_id INT PRIMARY KEY, nome VARCHAR(100), email VARCHAR(100) ); CREATE TABLE pedidos ( pedido_id INT PRIMARY KEY, cliente_id INT, produto_id INT, quantidade INT, FOREIGN KEY (cliente_id) REFERENCES clientes(cliente_id), FOREIGN KEY (produto_id) REFERENCES produtos(produto_id) ); CREATE TABLE produtos ( produto_id INT PRIMARY KEY, nome VARCHAR(100), categoria VARCHAR(50) );
- Exemplo de tabela normalizada:
- Exemplo: Uma tabela de clientes onde cada cliente tem um ID único, nome e email.
- 1NF (Primeira Forma Normal): Cada atributo deve ser único e não deve conter valores repetidos. Tabelas devem ter uma chave primária.
-
Desnormalização: Saiba quando desnormalizar para melhorar performance, especialmente em sistemas de relatórios.
- Desnormalização: Em alguns casos, pode ser vantajoso desnormalizar dados para melhorar a performance de leitura, especialmente em sistemas de relatórios ou OLAP. Isso envolve combinar tabelas ou duplicar dados para evitar joins complexos.
- Exemplo de desnormalização: Combinar informações de clientes e pedidos em uma única tabela para consultas frequentes.
CREATE TABLE pedidos_completos ( pedido_id INT PRIMARY KEY, cliente_nome VARCHAR(100), produto VARCHAR(100), quantidade INT ); - Dica: Use desnormalização com cautela, pois pode levar a redundâncias e inconsistências nos dados.
- Exemplo de desnormalização: Combinar informações de clientes e pedidos em uma única tabela para consultas frequentes.
- Desnormalização: Em alguns casos, pode ser vantajoso desnormalizar dados para melhorar a performance de leitura, especialmente em sistemas de relatórios ou OLAP. Isso envolve combinar tabelas ou duplicar dados para evitar joins complexos.
-
Relacionamentos: Domine chaves primárias, chaves estrangeiras e como modelar relacionamentos 1:1, 1:N e N:N.
-
Chaves primárias: Identificam de forma única cada registro em uma tabela.
- Exemplo:
cliente_idem uma tabela de clientes.CREATE TABLE clientes ( cliente_id INT PRIMARY KEY, nome VARCHAR(100), email VARCHAR(100) );
- Exemplo:
-
Chaves estrangeiras: Referenciam chaves primárias em outras tabelas, estabelecendo relacionamentos.
- Exemplo:
cliente_idem uma tabela de pedidos que referencia a tabela de clientes.CREATE TABLE pedidos ( pedido_id INT PRIMARY KEY, cliente_id INT, produto VARCHAR(100), quantidade INT, FOREIGN KEY (cliente_id) REFERENCES clientes(cliente_id) );
- Exemplo:
-
Relacionamentos:
- 1:1 (Um para Um): Cada registro em uma tabela corresponde a um único registro em outra tabela.
- Exemplo: Uma tabela de usuários e uma tabela de perfis, onde cada usuário tem um perfil único.
CREATE TABLE usuarios ( usuario_id INT PRIMARY KEY, nome VARCHAR(100), email VARCHAR(100) ); CREATE TABLE perfis ( perfil_id INT PRIMARY KEY, usuario_id INT UNIQUE, bio TEXT, FOREIGN KEY (usuario_id) REFERENCES usuarios(usuario_id) );
- Exemplo: Uma tabela de usuários e uma tabela de perfis, onde cada usuário tem um perfil único.
- 1:N (Um para Muitos): Um registro em uma tabela pode estar relacionado a vários registros em outra tabela.
- Exemplo: Uma tabela de clientes e uma tabela de pedidos, onde cada cliente pode ter vários pedidos.
CREATE TABLE clientes ( cliente_id INT PRIMARY KEY, nome VARCHAR(100), email VARCHAR(100) ); CREATE TABLE pedidos ( pedido_id INT PRIMARY KEY, cliente_id INT, produto VARCHAR(100), quantidade INT, FOREIGN KEY (cliente_id) REFERENCES clientes(cliente_id) );
- Exemplo: Uma tabela de clientes e uma tabela de pedidos, onde cada cliente pode ter vários pedidos.
- N:N (Muitos para Muitos): Vários registros em uma tabela podem estar relacionados a vários registros em outra tabela. Isso é feito através de uma tabela intermediária.
- Exemplo: Uma tabela de alunos e uma tabela de cursos, onde um aluno pode estar matriculado em vários cursos e um curso pode ter vários alunos.
CREATE TABLE alunos ( aluno_id INT PRIMARY KEY, nome VARCHAR(100), email VARCHAR(100) ); CREATE TABLE cursos ( curso_id INT PRIMARY KEY, nome VARCHAR(100) ); CREATE TABLE matriculas ( aluno_id INT, curso_id INT, PRIMARY KEY (aluno_id, curso_id), FOREIGN KEY (aluno_id) REFERENCES alunos(aluno_id), FOREIGN KEY (curso_id) REFERENCES cursos(curso_id) );
- Exemplo: Uma tabela de alunos e uma tabela de cursos, onde um aluno pode estar matriculado em vários cursos e um curso pode ter vários alunos.
Exercício 5: Normalização
- 1:1 (Um para Um): Cada registro em uma tabela corresponde a um único registro em outra tabela.
-
Objetivo: Transformar uma tabela não normalizada em 3NF.
-
Tarefa: Dado um dataset não normalizado (ex.: tabela com
order_id,customer_name,customer_address,product_name,product_category,amount), crie:- Tabelas normalizadas (
customers,products,orders). - Escreva o SQL para criar as tabelas com chaves primárias e estrangeiras.
- Insira dados de exemplo e teste com uma query que junte as tabelas.
- Tabelas normalizadas (
-
Dica: Identifique redundâncias (ex.:
customer_namerepetido) e separe em tabelas relacionadas. -
Extra: Crie um diagrama ER simples (pode ser desenhado à mão ou em ferramentas como Lucidchart).
-
Diagramas ER: Saiba criar e interpretar diagramas de entidade-relacionamento.
- Diagramas ER (Entidade-Relacionamento): São representações gráficas de entidades (tabelas) e seus relacionamentos. Eles ajudam a visualizar a estrutura do banco de dados e a identificar chaves primárias, chaves estrangeiras e relacionamentos.
- Exemplo de diagrama ER:
- Entidades:
clientes,pedidos,produtos. - Relacionamentos:
clientestem muitospedidos,pedidoscontém muitosprodutos. - Ferramentas: Use ferramentas como Lucidchart, Draw.io ou até mesmo papel e caneta para desenhar diagramas ER simples.
- Entidades:
- Exemplo de diagrama ER:
- Diagramas ER (Entidade-Relacionamento): São representações gráficas de entidades (tabelas) e seus relacionamentos. Eles ajudam a visualizar a estrutura do banco de dados e a identificar chaves primárias, chaves estrangeiras e relacionamentos.
Exercício 6: Consultas
- Objetivo: Escrever consultas SQL para resolver problemas de negócios.
- Tarefa: Dado um dataset de vendas (
order_id,customer_id,product_id,order_date,amount), escreva queries que:- Calcule o total de vendas por mês.
- Liste os 10 produtos mais vendidos.
- Encontre os clientes com maior gasto total.
- Dica: Use
GROUP BY,ORDER BYe funções de agregação comoSUM,COUNTeAVG. - Extra: Crie uma view que mostre o total de vendas por cliente e mês, facilitando relatórios futuros.
4. Otimização de Performance
- Análise de Query Plans: Aprenda a ler planos de execução (
EXPLAIN PLANou equivalentes) para identificar gargalos.- EXPLAIN: Use o comando
EXPLAINpara analisar o plano de execução de uma query e identificar possíveis gargalos de performance.- Exemplo:
EXPLAIN SELECT nome, SUM(salario) FROM funcionarios GROUP BY nome; - Explicação:
- EXPLAIN: Informa ao banco de dados que você deseja ver o plano de execução da query.
- SELECT nome, SUM(salario): Seleciona o nome dos funcionários e a soma dos salários.
- FROM funcionarios: Indica a tabela de onde os dados serão extraídos.
- GROUP BY nome: Agrupa os resultados pelo nome do funcionário.
- Exemplo:
- EXPLAIN: Use o comando
- Otimização de consultas: Aprenda a otimizar queries, evitando joins desnecessários, usando índices e evitando subconsultas complexas.
- Dicas de otimização:
- Use índices: Crie índices em colunas frequentemente usadas em filtros (
WHERE), junções (JOIN) e ordenações (ORDER BY).CREATE INDEX idx_nome ON funcionarios(nome); - Evite joins desnecessários: Use apenas as tabelas necessárias para a consulta.
- Minimize subconsultas: Use joins ou CTEs quando possível, pois subconsultas podem ser menos eficientes.
- Use
EXISTSem vez deIN: Em alguns casos,EXISTSpode ser mais eficiente queIN.SELECT nome FROM funcionarios WHERE EXISTS (SELECT 1 FROM departamentos WHERE departamentos.id = funcionarios.departamento_id); - Limite o número de registros retornados: Use
LIMITouTOPpara restringir o número de resultados.SELECT nome FROM funcionarios ORDER BY salario DESC LIMIT 10;
- Use índices: Crie índices em colunas frequentemente usadas em filtros (
- Dicas de otimização:
- Índices Estratégicos: Saiba quando criar índices compostos ou cobertos e como evitar over-indexing.
- Dicas de índices:
- Evitar maus hábitos: Minimize o uso de
SELECT *, subqueries desnecessárias ou loops em procedures. - Particionamento e Sharding: Entenda como particionar tabelas grandes ou distribuir dados em bancos maiores.
Exercício 6: Análise e Otimização de Query
- Objetivo: Identificar e melhorar uma query lenta.
- Tarefa: Escreva uma query que filtre uma tabela grande (ex.:
orderscom milhões de registros) por data e categoria, sem índices. Então:- Use
EXPLAIN(ou equivalente) para analisar o plano de execução. - Crie um índice apropriado (ex.: índice composto em
order_dateecategory). - Compare o desempenho antes e depois do índice.
- Use
- Dica: Use um dataset grande (ex.: do Google BigQuery) or gere dados sintéticos com ferramentas como
pgbench(PostgreSQL). - Extra: Teste o impacto de adicionar um índice desnecessário (over-indexing) na performance de
INSERT.
5. Conhecimento de Bancos Específicos
- Dialetos SQL: Cada banco de dados (MySQL, PostgreSQL, SQL Server, Oracle, etc.) tem particularidades. Estude as diferenças em sintaxe, funções específicas e ferramentas de administração.
- Ferramentas de administração: Familiarize-se com ferramentas como pgAdmin (PostgreSQL), SQL Server Management Studio (SSMS) ou Oracle SQL Developer.
- Configurações do banco: Entenda conceitos como configuração de memória, cache e tuning básico do servidor.
Exercício 7: SQL + Python
-
Objetivo: Conectar SQL a Python para análise de dados.
-
Tarefa: Usando Python com
pandaseSQLAlchemy, conecte-se a um banco (ex.: SQLite ou PostgreSQL) e:- Execute uma query que calcule o total de vendas por mês.
- Exporte o resultado para um arquivo CSV.
- Gere um gráfico simples (ex.: barras) com
matplotlib.
-
Dica: Use um dataset público como o "Northwind" ou "AdventureWorks".
-
Extra: Crie um script que automatize a extração diária de dados e envie por e-mail (usando
smtplib). -
Objetivo: Implementar auditoria com triggers.
-
Tarefa: Em uma tabela de produtos (
product_id,name,price), crie:- Uma tabela de auditoria (
audit_log) para registrar alterações no preço. - Um trigger que insira um registro em
audit_logsempre que o preço de um produto for atualizado.
- Uma tabela de auditoria (
-
Dica: Use
AFTER UPDATEno trigger e capture valores antigos e novos comOLDeNEW(em PostgreSQL/MySQL). -
Extra: Adicione uma query que mostre o histórico de alterações de preço para um produto específico.
6. Habilidades Práticas e de Negócio
- Resolução de problemas reais: Participe de projetos onde você precise extrair insights de dados, criar relatórios ou resolver problemas de negócio com SQL.
- Integração com outras ferramentas: Aprenda a conectar SQL com linguagens como Python (usando bibliotecas como SQLAlchemy ou pandas) ou ferramentas de BI (Power BI, Tableau).
- Documentação e legibilidade: Escreva queries claras, com comentários e padrões de nomenclatura consistentes.
- Segurança: Entenda como evitar SQL Injection e implementar boas práticas de segurança, como controle de acesso e criptografia de dados sensíveis.
7. Soft Skills e Experiência
- Comunicação: Saiba explicar suas queries e decisões técnicas para equipes não técnicas (ex.: analistas de negócio).
- Colaboração: Trabalhe bem com desenvolvedores, analistas de dados e administradores de banco (DBAs).
- Proatividade: Identifique problemas de performance ou modelagem antes que sejam apontados.
- Experiência prática: Busque projetos reais, como freelas, contribuições em open-source ou desafios internos na empresa.
8. Certificações e Estudo Contínuo
- Considere certificações específicas, como:
- Microsoft Certified: Data Analyst Associate (para SQL Server).
- Oracle Database SQL Certified Associate.
- PostgreSQL Certified Professional (se disponível).
- Estude livros como:
- SQL Performance Explained de Markus Winand.
- SQL for Data Scientists de Renee M. P. Teate.
- Acompanhe blogs, fóruns e comunidades como Stack Overflow, Reddit ou grupos no X para se manter atualizado.
9. Prática e Portfólio
- Projetos práticos: Crie um portfólio com exemplos de queries complexas, scripts de automação ou dashboards baseados em SQL.
- Datasets reais: Use datasets públicos (Kaggle, Google BigQuery) para simular cenários de negócio.
- Simulações de entrevistas: Pratique resolver problemas de SQL em tempo real, como os encontrados em entrevistas técnicas.
10. Mindset de Pleno
- Autonomia: Resolva problemas sem depender de supervisão constante.
- Visão de negócio: Entenda como suas queries impactam o negócio (ex.: relatórios que orientam decisões estratégicas).
- Mentoria: Comece a ajudar colegas juniores, compartilhando conhecimento.
Plano de Ação
- Avalie seu nível atual: Identifique lacunas em suas habilidades com testes práticos ou revisando projetos.
- Estude e pratique diariamente: Dedique 1-2 horas por dia a exercícios e projetos.
- Participe de projetos reais: Busque oportunidades na empresa ou em freelas para aplicar o conhecimento.
- Peça feedback: Mostre suas queries a colegas sêniores ou DBAs para sugestões de melhoria.
- Monitore sua evolução: Após 6-12 meses de prática consistente, avalie se você está pronto para assumir responsabilidades de um pleno.
Recursos Adicionais
- Cursos online: Plataformas como Coursera, Udemy e DataCamp oferecem cursos avançados em SQL.
- Livros: SQL Performance Explained (Markus Winand).
- Blogs e sites: SQLServerCentral, DataCamp Blog, Mode Analytics SQL Tutorial.
- Comunidades: Participe de fóruns como Stack Overflow, Reddit (r/SQL) e grupos no LinkedIn para trocar experiências e tirar dúvidas.
Publicado por Jefferson Peixoto em 07 de junho de 2025