Consultas SQL

Seleção, junções, NULL, agregação e resultados sem duplicações acidentais.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

Linhas, filtros e ordem

FROM e junções definem as linhas; WHERE filtra-as; SELECT escolhe ou calcula colunas; ORDER BY ordena.

  • SQL conserva duplicados por omissão; DISTINCT elimina repetições da combinação completa. Não uses DISTINCT para esconder uma junção errada: agrupa por chave, não por nome.
  • Só ORDER BY garante ordem. Com empates, define desempate para uma linha ou conserva todos os máximos em vez de LIMIT 1 isolado.
  • BETWEEN inclui limites; em LIKE, % aceita qualquer sequência e _ um carácter. Maiúsculas dependem do motor e da collation; AND precede OR, por isso explicita grupos com parênteses.

Junções sem multiplicar mal

JOIN ... ON conserva correspondências; LEFT JOIN conserva a esquerda, com NULL à direita sem correspondência. Condição no ON escolhe correspondências; no WHERE, filtra o resultado.

Ficheiros do exemplo
Contar encomendas, incluindo clientes sem compras
SELECT c.id, c.nome, COUNT(e.id) AS encomendas
FROM Cliente AS c
LEFT JOIN Encomenda AS e ON e.idCliente = c.id
GROUP BY c.id, c.nome
ORDER BY c.id;
PRAGMA foreign_keys = ON;
CREATE TABLE Cliente (
  id INTEGER PRIMARY KEY,
  nome TEXT NOT NULL,
  email TEXT UNIQUE
);
CREATE TABLE Produto (
  id INTEGER PRIMARY KEY,
  nome TEXT NOT NULL,
  precoCentimos INTEGER NOT NULL CHECK (precoCentimos >= 0),
  stock INTEGER NOT NULL CHECK (stock >= 0)
);
CREATE TABLE Encomenda (
  id INTEGER PRIMARY KEY,
  data TEXT NOT NULL,
  idCliente INTEGER NOT NULL REFERENCES Cliente(id)
);
CREATE TABLE Item (
  idEncomenda INTEGER NOT NULL REFERENCES Encomenda(id) ON DELETE CASCADE,
  idProduto INTEGER NOT NULL REFERENCES Produto(id),
  qtd INTEGER NOT NULL CHECK (qtd > 0),
  precoUnitario INTEGER NOT NULL CHECK (precoUnitario >= 0),
  PRIMARY KEY (idEncomenda, idProduto)
);
INSERT INTO Cliente VALUES
  (1, 'Ana', 'ana@example.test'),
  (2, 'Rui', NULL),
  (3, 'Mia', NULL);
INSERT INTO Produto VALUES
  (10, 'Teclado', 4500, 20),
  (11, 'Rato', 2500, 50),
  (12, 'Monitor', 18000, 5);
INSERT INTO Encomenda VALUES
  (100, '2026-01-05', 1),
  (101, '2026-01-06', 1),
  (102, '2026-01-06', 2);
INSERT INTO Item VALUES
  (100, 10, 2, 4500),
  (100, 11, 1, 2500),
  (101, 12, 1, 18000),
  (102, 11, 3, 2500);
Resultado

Executa a consulta para ver as tabelas.

Ana/2, Rui/1, Mia/0: COUNT(e.id) ignora o NULL da linha artificial de Mia, COUNT(*) contá-la-ia. Para filtrar por data sem perder Mia, põe a data no ON, não no WHERE.

  • Juntar Item multiplica encomendas por produtos: Ana passa a três linhas de compra. Conta encomendas com COUNT(DISTINCT e.id) e soma totais já agregados sem voltar a juntar.
  • Numa autojunção de pares, usa aliases, exige o mesmo cliente e e1.id < e2.id: exclui autorreferência e a ordem inversa.
  • NATURAL JOIN iguala todos os nomes comuns, mesmo com significados diferentes.

NULL a três valores

Comparar com NULL dá desconhecido; WHERE só aceita verdadeiro. Testa com IS NULL e IS NOT NULL.

CombinaçãoResultado
NOT desconhecidodesconhecido
falso AND desconhecidofalso
verdadeiro OR desconhecidoverdadeiro
restantes com desconhecidodesconhecido

preco > 30 OR preco <= 30 não cobre preço NULL. COALESCE(x, alt) escolhe o primeiro não nulo; só o tornes zero quando essa for a interpretação certa.

Agregar por grupos

WHERE filtra linhas antes de agrupar; HAVING filtra grupos depois. Para encomendas acima de 100 euros: agrupa Item por idEncomenda e HAVING SUM(qtd * precoUnitario) > 10000.

  • COUNT(*) conta linhas; COUNT(x) e COUNT(DISTINCT x) ignoram nulos. SUM, AVG, MIN, MAX ignoram nulos: média de 10, NULL, 20 é 15.
  • Sem linhas e sem GROUP BY, uma linha com COUNT 0 e resto NULL; com GROUP BY, nenhuma linha.
  • Colunas da resposta vão no agrupamento ou em agregações; a tolerância de SQLite a colunas soltas não é portátil.

CASE sem ELSE dá NULL quando nada corresponde. Datas ISO uniformes ordenam-se como texto; durações pedem funções de data, como julianday, não subtração de textos.

Exemplos de filtros e agregação.

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.