# 📘 SQL para Concursos — Banca FCC > Resumo completo com foco nas questões da FCC: ordem de execução, cláusulas, funções, joins, subqueries e pegadinhas clássicas. --- ## 1. ESTRUTURA GERAL DE UMA QUERY SELECT ```sql SELECT [colunas / expressões / funções de agregação] FROM [tabela(s)] JOIN [tabela] ON [condição] WHERE [filtro de linhas] GROUP BY [colunas de agrupamento] HAVING [filtro sobre grupos] ORDER BY [colunas de ordenação] LIMIT [quantidade de linhas] -- nem sempre cobrado ``` --- ## 2. ORDEM DE EXECUÇÃO (LÓGICA) ⚠️ CUIDADO NAS PROVAS A FCC cobra bastante a **ordem em que o banco de dados processa** as cláusulas — que é **diferente** da ordem em que escrevemos. | Passo | Cláusula | O que faz | |-------|----------------|----------------------------------------------| | 1 | `FROM` | Define as tabelas (e produto cartesiano) | | 2 | `JOIN` | Aplica os joins | | 3 | `WHERE` | Filtra as linhas (antes do agrupamento) | | 4 | `GROUP BY` | Agrupa as linhas | | 5 | `HAVING` | Filtra os grupos (depois do agrupamento) | | 6 | `SELECT` | Seleciona / calcula as colunas | | 7 | `DISTINCT` | Remove duplicatas | | 8 | `ORDER BY` | Ordena o resultado | | 9 | `LIMIT/OFFSET` | Limita a quantidade de linhas retornadas | ![image](https://hackmd.io/_uploads/rkKLsNbp-g.png) > **Pegadinha clássica FCC:** `WHERE` **não pode usar** alias definidos no `SELECT` nem funções de agregação (`SUM`, `COUNT`, etc.), pois o `WHERE` é executado **antes** do `SELECT`. Use `HAVING` para filtrar agregações. --- ## 3. DIFERENÇA ENTRE WHERE e HAVING | Característica | WHERE | HAVING | |------------------------|------------------------------|-------------------------------| | Momento de execução | Antes do GROUP BY | Depois do GROUP BY | | Filtra | Linhas individuais | Grupos | | Pode usar agregação? | ❌ Não | ✅ Sim | | Pode usar sem GROUP BY?| ✅ Sim | ✅ Sim (filtra resultado total)| ```sql -- ✅ CORRETO SELECT departamento, COUNT(*) AS total FROM funcionarios WHERE salario > 1000 -- filtra linhas antes de agrupar GROUP BY departamento HAVING COUNT(*) > 5; -- filtra grupos após agrupar -- ❌ ERRADO — FCC adora essa pegadinha! SELECT departamento, COUNT(*) AS total FROM funcionarios WHERE COUNT(*) > 5 -- ERRO: não pode usar agregação no WHERE GROUP BY departamento; ``` --- ## 4. FUNÇÕES DE AGREGAÇÃO | Função | Descrição | |---------------|------------------------------------------------| | `COUNT(*)` | Conta todas as linhas (incluindo NULLs) | | `COUNT(col)` | Conta linhas onde col **não é NULL** | | `SUM(col)` | Soma os valores (ignora NULL) | | `AVG(col)` | Média dos valores (ignora NULL) | | `MAX(col)` | Maior valor | | `MIN(col)` | Menor valor | > **Atenção:** `COUNT(*)` ≠ `COUNT(coluna)`. Se a coluna tiver NULLs, `COUNT(coluna)` retornará menos. --- ## 5. TIPOS DE JOIN ``` Tabela A Tabela B [ A ∩ B ] ``` | JOIN | Retorna | |-----------------|------------------------------------------------------------| | `INNER JOIN` | Apenas linhas com correspondência em **ambas** as tabelas | | `LEFT JOIN` | Todas de A + correspondências de B (B sem match = NULL) | | `RIGHT JOIN` | Todas de B + correspondências de A (A sem match = NULL) | | `FULL OUTER JOIN`| Todas de A e B (sem match = NULL em qualquer lado) | | `CROSS JOIN` | Produto cartesiano (todas as combinações) | | `SELF JOIN` | Join da tabela com ela mesma (usa alias) | ```sql -- INNER JOIN SELECT e.nome, d.nome AS departamento FROM empregado e INNER JOIN departamento d ON e.dep_id = d.id; -- LEFT JOIN — inclui empregados SEM departamento SELECT e.nome, d.nome AS departamento FROM empregado e LEFT JOIN departamento d ON e.dep_id = d.id; -- SELF JOIN — encontrar funcionário e seu gerente SELECT e.nome AS funcionario, g.nome AS gerente FROM funcionario e JOIN funcionario g ON e.gerente_id = g.id; ``` ![image](https://hackmd.io/_uploads/SypOiE-pWl.png) > **FCC cobra:** qual join retorna linhas sem correspondência e de qual lado. --- ## 6. SUBQUERIES (SUBCONSULTAS) ### 6.1 No WHERE ```sql -- Funcionários que ganham mais que a média SELECT nome FROM funcionario WHERE salario > (SELECT AVG(salario) FROM funcionario); ``` ### 6.2 Correlacionadas A subquery referencia a query externa — executada **uma vez por linha** da query principal. ```sql SELECT nome FROM funcionario f WHERE salario > ( SELECT AVG(salario) FROM funcionario WHERE departamento_id = f.departamento_id ); ``` ### 6.3 EXISTS / NOT EXISTS ```sql -- Departamentos que têm pelo menos 1 funcionário SELECT nome FROM departamento d WHERE EXISTS ( SELECT 1 FROM funcionario WHERE departamento_id = d.id ); ``` ### 6.4 IN / NOT IN ```sql SELECT nome FROM funcionario WHERE departamento_id IN (SELECT id FROM departamento WHERE cidade = 'SP'); ``` > **Pegadinha FCC com NOT IN e NULL:** Se a subquery retornar algum NULL, `NOT IN` retorna **vazio**! Use `NOT EXISTS` para segurança. --- ## 7. OPERADORES DE CONJUNTO | Operador | Descrição | |---------------|-------------------------------------------------------------| | `UNION` | Une resultados, **remove duplicatas** | | `UNION ALL` | Une resultados, **mantém duplicatas** (mais rápido) | | `INTERSECT` | Retorna apenas linhas presentes nas **duas** consultas | | `EXCEPT` | Retorna linhas da 1ª consulta que **não estão** na 2ª | > **Regras obrigatórias:** Mesmo número de colunas e tipos compatíveis em cada posição. --- ## 8. FUNÇÕES DE STRING (mais cobradas pela FCC) | Função | Descrição | Exemplo | |--------------------------------|----------------------------------------|------------------------------------| | `UPPER(str)` | Converte para maiúsculas | `UPPER('sql')` → `'SQL'` | | `LOWER(str)` | Converte para minúsculas | `LOWER('SQL')` → `'sql'` | | `LENGTH(str)` / `LEN(str)` | Comprimento da string | `LENGTH('abc')` → `3` | | `SUBSTRING(str, pos, len)` | Extrai parte da string | `SUBSTRING('abcde', 2, 3)` → `'bcd'`| | `TRIM(str)` | Remove espaços dos dois lados | `TRIM(' x ')` → `'x'` | | `LTRIM` / `RTRIM` | Remove espaços da esquerda/direita | | | `CONCAT(a, b)` | Concatena strings | `CONCAT('a','b')` → `'ab'` | | `REPLACE(str, old, new)` | Substitui substring | | | `LIKE` | Comparação com padrão | `LIKE 'A%'` (começa com A) | **Wildcards do LIKE:** - `%` → qualquer sequência de caracteres (inclusive vazia) - `_` → exatamente **um** caractere qualquer --- ## 9. FUNÇÕES NUMÉRICAS | Função | Descrição | |------------------|----------------------------------| | `ROUND(n, d)` | Arredonda n com d casas decimais | | `FLOOR(n)` | Arredonda para baixo | | `CEILING(n)` | Arredonda para cima | | `ABS(n)` | Valor absoluto | | `MOD(a, b)` | Resto da divisão | | `POWER(a, b)` | a elevado a b | --- ## 10. FUNÇÕES DE DATA | Função | Descrição | |-------------------------------|-------------------------------------| | `CURRENT_DATE` | Data atual | | `CURRENT_TIMESTAMP` / `NOW()` | Data e hora atual | | `EXTRACT(parte FROM data)` | Extrai ano, mês, dia, hora... | | `DATEDIFF(d1, d2)` | Diferença entre datas (dias) | | `DATE_ADD(data, INTERVAL n)` | Adiciona intervalo à data | ```sql SELECT EXTRACT(YEAR FROM data_admissao) AS ano FROM funcionario; ``` --- ## 11. NULL — COMPORTAMENTO ESPECIAL ⚠️ - Qualquer operação aritmética com NULL resulta em **NULL** - Qualquer comparação com NULL resulta em **NULL** (não TRUE, não FALSE) - Use `IS NULL` e `IS NOT NULL` para verificar - `NULL = NULL` → **FALSE** (ou NULL, dependendo do contexto) - `COALESCE(a, b, c)` → retorna o **primeiro valor não-NULL** - `NULLIF(a, b)` → retorna NULL se a = b, senão retorna a ```sql -- ❌ ERRADO WHERE salario = NULL -- ✅ CORRETO WHERE salario IS NULL -- COALESCE SELECT COALESCE(comissao, 0) FROM funcionario; -- substitui NULL por 0 ``` --- ## 12. DDL — COMANDOS DE DEFINIÇÃO | Comando | Descrição | |------------------|------------------------------------| | `CREATE TABLE` | Cria tabela | | `ALTER TABLE` | Altera estrutura da tabela | | `DROP TABLE` | Remove tabela e seus dados | | `TRUNCATE TABLE` | Remove **todos os dados** da tabela (mais rápido que DELETE sem WHERE) | | `CREATE INDEX` | Cria índice | | `CREATE VIEW` | Cria visão | ```sql CREATE TABLE produto ( id INT PRIMARY KEY, nome VARCHAR(100) NOT NULL, preco DECIMAL(10,2), cat_id INT REFERENCES categoria(id) -- FK ); ALTER TABLE produto ADD COLUMN estoque INT DEFAULT 0; ALTER TABLE produto DROP COLUMN estoque; ``` --- ## 13. DML — COMANDOS DE MANIPULAÇÃO ```sql -- INSERT INSERT INTO produto (id, nome, preco) VALUES (1, 'Caneta', 2.50); -- UPDATE UPDATE produto SET preco = 3.00 WHERE id = 1; -- DELETE DELETE FROM produto WHERE id = 1; -- TRUNCATE (sem WHERE, não pode ter rollback em alguns SGBDs) TRUNCATE TABLE produto; ``` > **Diferença DELETE vs TRUNCATE:** > - `DELETE` pode ter `WHERE`, pode fazer rollback, dispara triggers > - `TRUNCATE` remove tudo, geralmente mais rápido, pode não disparar triggers --- ## 14. DCL — CONTROLE DE ACESSO ```sql GRANT SELECT, INSERT ON produto TO usuario1; REVOKE INSERT ON produto FROM usuario1; ``` --- ## 15. TCL — CONTROLE DE TRANSAÇÕES ```sql BEGIN; -- inicia transação COMMIT; -- confirma alterações ROLLBACK; -- desfaz alterações SAVEPOINT sp1; -- cria ponto de salvamento ROLLBACK TO sp1; -- volta ao savepoint ``` ### Propriedades ACID | Propriedade | Descrição | |---------------|------------------------------------------------------------| | **A**tomicity | A transação é tudo ou nada | | **C**onsistency | O banco vai de um estado válido para outro válido | | **I**solation | Transações concorrentes não interferem entre si | | **D**urability | Após COMMIT, as mudanças persistem mesmo com falha | --- ## 16. CONSTRAINTS (RESTRIÇÕES) | Constraint | Descrição | |-----------------|------------------------------------------------------| | `PRIMARY KEY` | Identifica unicamente cada linha (NOT NULL + UNIQUE) | | `FOREIGN KEY` | Referencia PK de outra tabela | | `UNIQUE` | Valores únicos (permite NULL, depende do SGBD) | | `NOT NULL` | Não permite valor nulo | | `CHECK` | Valida condição | | `DEFAULT` | Valor padrão quando não informado | --- ## 17. VIEWS (VISÕES) ```sql CREATE VIEW vw_funcionarios_sp AS SELECT nome, salario FROM funcionario WHERE cidade = 'SP'; -- Consultar a view como se fosse tabela SELECT * FROM vw_funcionarios_sp; DROP VIEW vw_funcionarios_sp; ``` > **FCC cobra:** Views são consultas armazenadas, **não armazenam dados físicos** (exceto materialized views). Simplificam consultas complexas e podem restringir acesso. --- ## 18. ÍNDICES ```sql CREATE INDEX idx_func_nome ON funcionario(nome); CREATE UNIQUE INDEX idx_func_cpf ON funcionario(cpf); DROP INDEX idx_func_nome; ``` > Índices **aceleram leituras** (`SELECT`) mas **penalizam escritas** (`INSERT`, `UPDATE`, `DELETE`). A PRIMARY KEY cria índice automaticamente. --- ## 19. DISTINCT e GROUP BY — DIFERENÇAS ```sql -- DISTINCT: remove linhas duplicadas no resultado final SELECT DISTINCT departamento FROM funcionario; -- GROUP BY: agrupa para usar funções de agregação SELECT departamento, COUNT(*) FROM funcionario GROUP BY departamento; ``` > `GROUP BY` sem função de agregação se comporta de forma semelhante ao `DISTINCT`, mas são conceitualmente diferentes. --- ## 20. ORDER BY ```sql SELECT nome, salario FROM funcionario ORDER BY salario DESC, nome ASC; -- Pode usar número da coluna (FCC adora cobrar isso) ORDER BY 2 DESC, 1 ASC; -- equivalente ao anterior ``` - `ASC` → crescente (padrão, pode omitir) - `DESC` → decrescente - NULL: comportamento varia por SGBD (geralmente vai para o final no ASC) --- ## 21. CASE WHEN ```sql SELECT nome, CASE WHEN salario < 2000 THEN 'Baixo' WHEN salario < 5000 THEN 'Médio' ELSE 'Alto' END AS faixa_salarial FROM funcionario; ``` --- ## 22. PEGADINHAS CLÁSSICAS DA FCC ⚠️ 1. **`WHERE` com agregação** → ERRO. Use `HAVING`. 2. **`NOT IN` com NULL na subquery** → retorna zero linhas. 3. **`COUNT(*)` vs `COUNT(coluna)`** → NULL é ignorado no segundo. 4. **Alias do SELECT não pode ser usado no WHERE** (mas pode no ORDER BY em alguns SGBDs). 5. **`UNION` remove duplicatas, `UNION ALL` não** → impacto na performance. 6. **`DELETE` sem WHERE** apaga tudo mas é diferente de `TRUNCATE`. 7. **`NULL = NULL` é FALSE** → sempre use `IS NULL`. 8. **`BETWEEN a AND b`** → inclusivo nos dois extremos. 9. **`LIKE '%texto%'`** → não usa índice, lento em tabelas grandes. 10. **Produto cartesiano sem JOIN condition** → `FROM A, B` sem WHERE gera todas as combinações. --- ## 23. EXEMPLOS DE QUESTÕES FCC — PADRÃO ### Questão tipo: "Qual o resultado da query?" ```sql SELECT d.nome, COUNT(f.id) AS qtd FROM departamento d LEFT JOIN funcionario f ON f.dep_id = d.id GROUP BY d.nome HAVING COUNT(f.id) >= 2 ORDER BY qtd DESC; ``` > Retorna departamentos com **2 ou mais** funcionários, ordenados do maior para o menor. Departamentos sem funcionários **não** aparecem (por causa do HAVING filtrando COUNT = 0). --- ### Questão tipo: "Qual cláusula está incorreta?" ```sql SELECT departamento, AVG(salario) FROM funcionario WHERE AVG(salario) > 3000 -- ❌ ERRADO GROUP BY departamento; ``` > Deve substituir `WHERE` por `HAVING`. --- *Resumo elaborado com foco nas cobranças recorrentes da banca FCC em concursos públicos de TI e áreas afins.* **EXTRA** Trabalhando com datas em 3 diferentes bancos de dado. ![17767263687804260213628430476498](https://hackmd.io/_uploads/HyQsWV4pbe.jpg) Sintaxe do