Junções SQL e relacionamentos entre tabelas

Aprenda a combinar dados de tabelas relacionadas em SQL. Siga chaves primárias e estrangeiras de uma tabela a outra, escreva junções internas e preserve linhas sem correspondência com junções externas à esquerda, à direita e completas. Junte uma tabela a ela mesma, gere todas as combinações com uma junção cruzada e responda a perguntas sobre relacionamentos muitos para muitos por meio de tabelas associativas e cadeias de três ou mais tabelas. Por fim, aprenda a identificar linhas duplicadas, totais inflados e linhas perdidas e a verificar o resultado de uma junção antes de confiar nele. A maioria dos exemplos usa um pequeno banco de dados de loja, com pequenas tabelas adicionais para hierarquias, relacionamentos muitos para muitos e combinações. Todos os exemplos mostram suas linhas de resultado reais.

BásicoAula 5 de 6 do curso Curso de Noções básicas de SQL

O que você vai aprender

  1. Entenda como as tabelas são vinculadas por chaves e explique o que uma junção faz com suas linhas antes de escrevê-la.
    • Identificar os vínculos entre tabelas em um esquema
      Use chaves primárias e estrangeiras para entender como as tabelas se relacionam, classifique cada relacionamento como um para um, um para muitos ou muitos para muitos e planeje quais colunas uma junção deve relacionar.
    • Explicar o efeito de uma junção sobre as linhas
      Descreva uma junção como a formação de pares de linhas que atendem a uma condição, preveja a largura e o número de linhas do resultado e use apelidos de tabela e nomes de coluna qualificados.
  2. Escreva junções internas que retornam apenas linhas com correspondência nas duas tabelas, usando ON, USING e condições de intervalo, e filtre e ordene as linhas combinadas.
    • Escrever uma junção interna com ON
      Junte duas tabelas por suas colunas de chave com JOIN ... ON, preveja exatamente quais linhas serão retornadas e adicione filtros, ordenação e nomes claros para as colunas.
    • Usar USING, NATURAL JOIN, junções por vírgulas e condições de intervalo
      Reconheça outras formas de escrever uma junção interna, explique o risco de cada uma e junte linhas por um intervalo em vez de uma igualdade entre chaves.
  3. Use junções externas à esquerda, à direita e completas para preservar linhas sem correspondência, encontrar dados ausentes e posicionar cada condição para que filtre o que você pretende.
    • Preservar todas as linhas de uma tabela com LEFT JOIN
      Escreva uma junção externa à esquerda, preveja suas linhas com colunas preenchidas com NULL e use-a para encontrar linhas sem correspondência em outra tabela.
    • Usar RIGHT JOIN e FULL OUTER JOIN
      Preserve linhas sem correspondência da tabela à direita ou das duas tabelas, reescreva uma junção à direita como junção à esquerda e use uma junção completa para comparar duas listas.
    • Posicionar condições corretamente em ON ou WHERE
      Explique por que uma condição se comporta de forma diferente em ON e em WHERE de uma junção externa e escolha a posição correta para cada condição.
  4. Use autojunções para relacionar linhas dentro de uma tabela, use junções cruzadas para gerar todas as combinações e reconheça uma junção cruzada que ocorreu por acidente.
    • Relacionar linhas da mesma tabela com uma autojunção
      Junte uma tabela a ela mesma com dois apelidos para seguir referências dentro da tabela, como funcionários e seus gerentes, e para formar pares de linhas da mesma tabela.
    • Gerar todas as combinações com uma junção cruzada
      Use CROSS JOIN para formar pares entre cada linha de uma tabela e cada linha de outra, preveja o tamanho do resultado e identifique produtos cartesianos acidentais.
  5. Use tabelas associativas para responder a perguntas sobre relacionamentos muitos para muitos e junte três ou mais tabelas em uma consulta, preservando as linhas corretas em cada etapa.
    • Consultar relacionamentos muitos para muitos por meio de uma tabela associativa
      Explique como uma tabela associativa vincula duas tabelas e faça junções por meio dela para responder a perguntas nos dois sentidos, incluindo linhas sem correspondente.
    • Juntar três ou mais tabelas em uma consulta
      Planeje um caminho de chaves por várias tabelas, escreva uma junção por vínculo e interprete o que cada linha de um resultado com várias tabelas representa.
    • Preservar linhas sem correspondência ao longo de uma cadeia de junções
      Combine junções externas e internas em uma cadeia sem perder as linhas que você pretendia preservar e verifique cada etapa da cadeia.
  6. Reconheça quando uma junção multiplica ou perde linhas, corrija contagens e totais inflados e verifique o resultado de uma junção antes de confiar nele.
    • Corrigir linhas duplicadas e totais inflados
      Explique por que junções em vínculos um para muitos repetem linhas e conte e some valores no nível adequado para manter os totais corretos.
    • Verificar o resultado de uma junção antes de confiar nele
      Preveja quantas linhas uma junção deve retornar, reconheça os sinais de erros comuns de junção e siga uma breve lista de verificação para cada consulta com junção.

Guia de estudo de Junções SQL

6 capítulos

1

Chaves e linhas combinadas

Uma junção começa com um relacionamento entre linhas. Os dados dos clientes e dos pedidos ficam em tabelas separadas, e as chaves indicam como reuni-los. Leia o esquema da pequena loja, distinga vínculos um para um, um para muitos e muitos para muitos e trace um caminho para um relatório. Depois, acompanhe como pares correspondentes se tornam linhas de resultado, por que nomes podem se repetir e como apelidos deixam clara a origem de cada coluna selecionada.

1.1 Chaves e caminhos entre tabelas

O endereço de um cliente pertence aos dados do cliente. A data de um pedido pertence aos dados do pedido. Manter esses dados em tabelas separadas reduz a repetição, mas um relatório frequentemente precisa de dados de ambas. Uma junção combina suas linhas dentro de uma consulta.

Leia as chaves

Uma chave primária identifica uma linha. Ela pode ser uma coluna ou várias colunas juntas. Uma chave estrangeira se refere a uma chave primária ou outra chave única, em outra tabela ou na mesma tabela. No banco de dados da loja, orders.customer_id aponta para customers.customer_id.

customer_idnamecity
1AnaDenver
2BenAustin
3ChloeDenver
4DevBoston
order_idcustomer_idorder_datetotal
10112026-03-0222,00
10212026-03-1525,50
10322026-03-2060,00
104NULL2026-03-2115,00

Os pedidos 101 e 102 se referem ao cliente 1, Ana. O pedido 103 se refere a Ben. O pedido 104 é uma compra sem cadastro: sua chave de cliente é NULL, então não se refere a nenhum cliente. O número do pedido identifica o pedido; ele não identifica o cliente. Juntar order_id a customer_id compararia identificadores sem relação entre si.

Classifique o relacionamento
RelacionamentoSignificadoOnde fica o vínculo
Um para umCada linha tem no máximo um correspondente no outro lado.Uma chave estrangeira também é única, como no caso de um crachá por funcionário.
Um para muitosUma linha pai pode ter várias linhas filhas; cada linha filha tem no máximo uma linha pai.A chave estrangeira fica no lado muitos, como em orders.
Muitos para muitosAs linhas de ambos os lados podem ter vários correspondentes.Uma tabela associativa contém uma chave estrangeira para cada lado.

O relacionamento cliente–pedido é um para muitos. Um cliente pode não ter pedidos, ter um pedido ou vários. Isso não significa que a tabela de clientes armazene um identificador de pedido para cada compra. Cada pedido armazena sua própria referência ao cliente.

Para alunos e cursos, nenhum dos lados pode conter apenas uma referência para descrever todos os vínculos. Uma linha de enrollments registra um par aluno–curso. Várias linhas de matrícula podem se referir ao mesmo aluno, e várias podem se referir ao mesmo curso.

Trace um caminho antes de escrever SQL

Para listar os produtos comprados por cada cliente, siga customers → orders → order_items → products. Os vínculos usam customer_id, depois order_id e depois product_id. Cada vínculo precisa de sua própria condição. Um item do pedido fornece a conexão que falta entre um pedido e um produto.

Leia o significado do esquema, não apenas a grafia das colunas. employees.manager_id pode se referir a employees.emp_id, embora os nomes sejam diferentes. Por outro lado, customers.name e products.name nomeiam tipos diferentes de coisas e não devem ser relacionados apenas porque ambos se chamam name.

Uma chave estrangeira declarada é uma orientação útil, mas SQL também pode juntar tabelas sem uma restrição declarada. Um preço pode corresponder a uma faixa de preço, e dois funcionários podem corresponder porque têm o mesmo gerente. A condição deve expressar o relacionamento necessário para a pergunta.

Principais conclusões

  • Uma chave primária identifica uma linha; uma chave estrangeira se refere a uma chave primária ou única.
  • A chave estrangeira fica no lado muitos de um relacionamento um para muitos.
  • Uma tabela associativa registra os pares em um relacionamento muitos para muitos.
  • Siga os vínculos do esquema e atribua a cada vínculo uma condição que faça sentido.

1.2 Como linhas correspondentes se tornam um resultado

Uma junção cria novas linhas combinando linhas de entrada. Comece pela regra de correspondência e depois pergunte quantos correspondentes cada linha tem. A resposta determina quais linhas aparecem e com que frequência seus valores se repetem.

Pense em pares

Para uma junção interna, imagine cada cliente ao lado de cada pedido. Mantenha um par apenas quando o.customer_id = c.customer_id for verdadeiro. O pedido 101 forma um par com Ana; ele não forma um par com Ben, Chloe ou Dev. O pedido 102 também forma um par com Ana. Um cliente pode, portanto, contribuir com várias linhas de resultado.

A condição pode ser verdadeira, falsa ou desconhecida. Uma igualdade que envolve NULL é desconhecida, então o pedido sem cadastro 104 não encontra um cliente correspondente. Uma junção externa também preserva linhas sem correspondência do lado escolhido e preenche as colunas do correspondente ausente com NULL.

Essa representação par a par explica as junções melhor que círculos sobrepostos. Uma junção não apenas reúne itens compartilhados: ela constrói linhas combinadas, e chaves repetidas podem criar mais linhas de saída do que qualquer uma das entradas contém. Se duas linhas de um lado e três do outro compartilham uma chave, essa chave produz seis pares correspondentes.

Escolha colunas independentemente das correspondências

A tabela de clientes da loja tem três colunas e a tabela de pedidos tem quatro. Com JOIN ... ON, SELECT * retorna todas as sete, incluindo as duas cópias de customer_id. Você pode selecionar apenas os campos necessários para o relatório:

SELECT c.name, o.order_id, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY o.order_id;

O resultado é (Ana; 101; 22,00), (Ana; 102; 25,50) e (Ben; 103; 60,00). As colunas de chave fazem seu trabalho de correspondência sem precisar aparecer na saída selecionada. Selecionar menos colunas altera a largura do resultado, não quais pares de entrada correspondem.

Dê nomes curtos e claros às tabelas

Em FROM customers c, c é um apelido de tabela. Refira-se às colunas dessa tabela como c.name e c.customer_id. A expressão c.name é um nome de coluna qualificado: a parte antes do ponto indica qual papel de tabela fornece o valor.

As duas tabelas da junção contêm customer_id. Escrever apenas SELECT customer_id com a forma ON deixa o banco de dados sem saber qual delas escolher e causa um erro de referência ambígua a coluna. Escreva c.customer_id ou o.customer_id de acordo com o valor necessário. Qualificar outras colunas selecionadas também facilita a identificação de sua origem.

AS antes de um apelido de tabela é opcional no PostgreSQL, SQLite, MySQL e SQL Server. O Oracle não o aceita, então FROM customers c é uma forma útil para todos eles. Depois de dar um apelido a uma tabela, use-o de forma consistente.

Leia a ordem lógica da consulta

FROM e suas junções criam as linhas combinadas. WHERE filtra essas linhas. SELECT escolhe as colunas de saída e ORDER BY ordena o resultado. Um filtro pode usar uma coluna de uma tabela da junção mesmo quando essa coluna não é selecionada. Por exemplo, WHERE c.city = 'Denver' pode filtrar um relatório que exibe apenas nomes e totais de pedidos.

Sem ORDER BY, o banco de dados não garante nenhuma ordem específica das linhas. Uma consulta que exibe Ana primeiro hoje pode exibir outra linha primeiro depois; a ordenação é uma instrução separada da correspondência.

Principais conclusões

  • Uma junção interna preserva cada par cuja condição é verdadeira.
  • Valores de chave repetidos podem produzir várias linhas para uma linha de entrada.
  • Apelidos e nomes qualificados identificam qual tabela fornece uma coluna.
  • As junções criam linhas antes de WHERE filtrá-las e SELECT escolher as colunas.
  • Use ORDER BY quando a ordem das linhas for importante.
2

Como escrever junções internas

Junções internas respondem a perguntas que exigem dados correspondentes dos dois lados, como o nome de um cliente ao lado de um pedido. Crie uma condição explícita, examine suas linhas de resultado reais e adicione filtros e ordenação. Depois, leia as formas abreviadas e antigas que você pode encontrar em consultas existentes. Correspondências por intervalo introduzem outro tipo de condição, em que faixas sobrepostas ou lacunas podem alterar o número de linhas produzidas por cada valor.

2.1 Relacionar linhas com JOIN e ON

Use uma junção interna quando uma linha de resultado precisar de uma correspondência nas duas tabelas. JOIN e INNER JOIN significam a mesma coisa. Nenhum dos dois preserva uma linha que não encontra correspondente.

Monte a consulta em três partes

Primeiro, nomeie as tabelas e seus papéis. Depois, declare o relacionamento em ON. Por fim, escolha as colunas a exibir.

SELECT c.name, o.order_id, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY o.order_id;

Leia a condição como “a referência ao cliente no pedido é igual ao identificador deste cliente”. Para o pedido 101, a referência é 1, então ele forma um par com Ana. O pedido 102 também tem referência 1, e o pedido 103 tem referência 2. O resultado completo é:

nameorder_idtotal
Ana10122,00
Ana10225,50
Ben10360,00

Ana aparece duas vezes porque tem dois pedidos correspondentes. Chloe e Dev não têm nenhum, então não aparecem. O pedido sem cadastro 104 tem uma referência de cliente NULL, que não satisfaz nenhuma igualdade com uma chave de cliente.

Filtre e ordene as linhas combinadas

Para mostrar apenas clientes de Denver, coloque WHERE c.city = 'Denver' após a junção e antes de ORDER BY. O resultado passa a ser (Ana; 101; 22,00) e (Ana; 102; 25,50). Chloe também mora em Denver, mas a junção interna nunca produziu uma linha para ela.

Em uma junção interna, colocar esse filtro em ON produz os mesmos pares. Uma convenção que facilita a leitura é manter as condições de correspondência entre tabelas em ON e os filtros do relatório em WHERE. Essa equivalência não se estende às junções externas.

Você pode ordenar por uma coluna de uma tabela da junção que não aparece na saída selecionada. Também pode omitir as chaves de junção da saída: a consulta acima faz a correspondência por customer_id enquanto exibe um nome, um número de pedido e um total. O papel de uma coluna na correspondência é separado de seu papel no relatório.

Compare todas as partes de uma chave

Alguns registros são identificados por um par de colunas. Um item de remessa que se refere a um item do pedido pode precisar dos identificadores tanto do pedido quanto do produto:

SELECT s.order_id, s.product_id, oi.quantity
FROM shipment_lines s
JOIN order_items oi
  ON s.order_id = oi.order_id
 AND s.product_id = oi.product_id;

As duas comparações devem ser verdadeiras para haver correspondência. Comparar apenas order_id associaria cada item de remessa a cada item de produto desse pedido. A consulta poderia ser executada com sucesso enquanto descreve as quantidades de produtos erradas.

Altere a ordem sem alterar o significado

Escrever FROM orders o JOIN customers c ON c.customer_id = o.customer_id produz os mesmos pares cliente–pedido. Inverter os dois lados de = também preserva uma igualdade. SELECT * pode organizar as colunas de forma diferente após a troca das tabelas, e a ordem das linhas continua indefinida a menos que sejam ordenadas.

Uma alteração muito mais séria é ON o.order_id = c.customer_id. As duas colunas contêm números, então isso é SQL válido, mas elas identificam coisas diferentes. Nos dados da loja, a consulta retorna zero linhas: os identificadores de pedido 101–104 nunca são iguais aos identificadores de cliente 1–4. Verifique o relacionamento no esquema mesmo quando o banco de dados não informa erro de sintaxe.

Principais conclusões

  • JOIN significa INNER JOIN: linhas sem correspondência de qualquer um dos lados são excluídas.
  • Coloque o relacionamento em ON e depois adicione filtros e ordenação para o relatório.
  • Compare todas as partes de uma chave composta com AND.
  • Um código SQL válido ainda pode comparar as colunas erradas.

2.2 Outras formas de declarar uma correspondência

ON torna uma condição explícita, mas códigos SQL existentes podem usar formas mais curtas ou antigas. Leia cada forma perguntando quais pares ela mantém. Algumas formas também alteram como as colunas compartilhadas aparecem na saída.

USING nomeia a chave compartilhada

Quando as colunas de chave têm o mesmo nome, esta consulta usa uma igualdade abreviada:

SELECT c.name, o.order_id
FROM customers c
JOIN orders o USING (customer_id)
ORDER BY o.order_id;

Ela retorna (Ana, 101), (Ana, 102) e (Ben, 103). USING (customer_id) significa comparar as duas colunas customer_id. Com SELECT *, retorna seis colunas, mostrando a chave compartilhada uma vez; JOIN ... ON inclui as duas colunas de chave das entradas.

Para uma chave composta, liste os dois nomes: USING (order_id, product_id). Cada coluna listada deve existir com esse nome nas duas entradas.

PostgreSQL, SQLite, MySQL e Oracle oferecem suporte a USING; SQL Server não. No Oracle, uma coluna nomeada em USING deve ser referenciada sem qualificação, então escreva SELECT customer_id, não SELECT c.customer_id. Outras colunas ainda podem usar seus apelidos de tabela.

NATURAL JOIN escolhe colunas para você

Um NATURAL JOIN compara todos os nomes de coluna compartilhados pelas entradas, combina esses testes de igualdade com AND e mostra as colunas compartilhadas uma vez. PostgreSQL, SQLite, MySQL e Oracle oferecem suporte a ele, mas SQL Server não.

Essa escolha automática pode alterar uma consulta sem aviso. Clientes e pedidos atualmente compartilham apenas customer_id. Adicionar uma coluna city a pedidos faz uma junção natural exigir correspondência tanto do identificador do cliente quanto da cidade. Uma cidade de entrega diferente da cidade do cliente pode então remover um pedido que antes tinha correspondência.

Clientes e produtos têm name, mas um nomeia uma pessoa e o outro nomeia um produto. A junção natural deles compararia esses nomes sem relação e não retornaria linhas nos dados da loja. Sem nomes de coluna compartilhados, uma junção natural retorna todas as combinações. Use ON ou uma lista USING intencional para manter a regra de correspondência visível.

Leia junções antigas por vírgulas
SELECT c.name, o.order_id
FROM customers c, orders o
WHERE o.customer_id = c.customer_id;

Isso retorna os mesmos três pares que a junção interna. A condição agora fica em WHERE. Se você a esquecer, todos os quatro clientes formarão pares com todos os quatro pedidos, produzindo 16 linhas. JOIN ... ON mantém cada tabela ao lado de sua própria condição, o que facilita a verificação de consultas mais longas.

Relacione um valor a um intervalo

Uma equijunção usa igualdade. Uma junção por desigualdade usa outra comparação, como um teste de intervalo:

SELECT p.name, b.band
FROM products p
JOIN price_bands b
  ON p.price BETWEEN b.min_price AND b.max_price;

As faixas são Budget 0,00–4,99, Standard 5,00–19,99 e Premium 20,00–999,99. Mug por 8,00 e Stapler por 12,00 correspondem a Standard; Pen por 1,50 e Notebook por 4,25 correspondem a Budget. Premium não tem produto correspondente e não contribui com nenhuma linha.

BETWEEN inclui os dois extremos. Uma nova faixa Gift de 8,00 a 15,00 daria a Mug e Stapler uma segunda correspondência para cada um. A lacuna entre 4,99 e 5,00 deixaria um preço de 4,995 sem correspondência. Os intervalos determinam o resultado assim como as chaves: um valor pode ter zero, uma ou várias correspondências.

Principais conclusões

  • USING compara as colunas listadas de mesmo nome e mostra cada chave compartilhada uma vez.
  • NATURAL JOIN depende de todos os nomes de coluna compartilhados, então alterações no esquema podem mudar seu resultado.
  • Uma junção por vírgulas precisa de sua condição de correspondência em WHERE.
  • Uma junção por desigualdade pode comparar intervalos; sobreposições criam correspondências extras e lacunas deixam valores sem correspondência.
  • O SQL Server usa ON, sem a sintaxe USING ou NATURAL JOIN.
3

Preservar linhas sem correspondência

Relatórios frequentemente precisam manter visíveis relacionamentos ausentes: clientes sem pedidos, produtos não vendidos ou registros ausentes de uma de duas listas. Junções externas preservam essas linhas e marcam o correspondente ausente com valores NULL. Escolha qual lado deve permanecer e depois acompanhe como as condições alteram o resultado quando são executadas durante a correspondência ou depois dela. A posição de um único teste de data pode determinar se um cliente inteiro desaparece.

3.1 Todas as linhas à esquerda, incluindo as sem correspondência

Um relatório que pede “todos os clientes, incluindo clientes sem pedidos” precisa de uma junção externa à esquerda. LEFT JOIN preserva cada linha à esquerda. Ele associa cada linha correspondente à direita ou fornece uma linha de valores NULL quando não há correspondência. A palavra OUTER é opcional.

Acompanhe a tabela preservada
SELECT c.name, o.order_id, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
ORDER BY c.customer_id, o.order_id;
nameorder_idtotal
Ana10122,00
Ana10225,50
Ben10360,00
ChloeNULLNULL
DevNULLNULL

Ana ainda fornece duas linhas. Uma junção à esquerda não reduz os pedidos de um cliente a um. Chloe e Dev fornecem exatamente uma linha cada, pois nenhum dos dois tem correspondência. Há cinco linhas no total: três pares correspondentes e dois clientes sem correspondência.

A junção retorna pelo menos tantas linhas quanto sua entrada à esquerda antes de filtros posteriores. Para cada linha à esquerda, conte suas correspondências; se não houver nenhuma, conte uma linha preenchida com NULL. Isso explica por que quatro clientes podem produzir cinco linhas.

O pedido sem cadastro 104 está ausente. Preservar todos os clientes não preserva também os pedidos sem correspondência. Para preservar todos os pedidos, comece com orders o LEFT JOIN customers c ON c.customer_id = o.customer_id. Selecionar o.order_id, c.name produz então (101, Ana), (102, Ana), (103, Ben) e (104, NULL). Chloe e Dev não aparecem mais.

Encontre linhas sem correspondente

Uma antijunção à esquerda mantém apenas as linhas que não encontraram correspondência:

SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;

A junção à esquerda primeiro cria todas as cinco linhas. WHERE mantém então Chloe e Dev, cujas chaves de pedido são NULL. O correspondente ausente é exatamente o que a consulta procura.

Escolha uma coluna do lado direito que não possa ser NULL em uma correspondência real. A chave primária de um pedido é um bom teste. Testar um coupon_code opcional também manteria pedidos correspondentes reais sem cupom, então isso não significaria “nenhum pedido”. Use IS NULL: = NULL é avaliado como desconhecido e não mantém nenhuma linha em WHERE.

O mesmo padrão encontra produtos não vendidos:

SELECT p.name
FROM products p
LEFT JOIN order_items oi ON oi.product_id = p.product_id
WHERE oi.order_id IS NULL;

Ele retorna (Stapler), o único produto sem item de pedido. Aqui uma linha correspondente real necessariamente tem um identificador de pedido, então o teste detecta a linha ausente.

Interprete um valor ausente antes de substituí-lo

Uma linha de junção externa preenchida com NULL significa que nenhum correspondente foi encontrado. Um NULL armazenado em um pedido real pode, por sua vez, significar que um campo não foi fornecido. Essas são situações diferentes, embora ambas sejam exibidas como NULL.

COALESCE(o.total, 0) escolhe o primeiro argumento que não é NULL. Ele exibiria 0 para Chloe e Dev. Isso pode ser útil para um relatório de gastos, mas um zero em uma coluna chamada “total do pedido” pode sugerir um pedido real de valor zero. Mantenha o rótulo e o significado do relatório alinhados.

Principais conclusões

  • Uma junção à esquerda preserva as linhas à esquerda e fornece valores NULL para os correspondentes ausentes à direita.
  • Conte cada par correspondente, mais uma linha para cada linha à esquerda sem correspondência.
  • Para uma antijunção, use WHERE right_key IS NULL em uma chave que não possa ser NULL em uma correspondência.
  • Uma linha à direita sem correspondência não é preservada por uma junção à esquerda.
  • COALESCE pode alterar a exibição de valores ausentes; escolha um rótulo que mantenha seu significado claro.

3.2 Preservar o lado direito ou ambos os lados

Às vezes, as linhas necessárias estão à direita de uma junção. Em outras situações, as duas entradas devem ser preservadas para que registros ausentes possam ser comparados. Junções externas à direita e completas tornam essas escolhas explícitas.

Reescreva uma junção à direita como junção à esquerda
SELECT c.name, o.order_id
FROM customers c
RIGHT JOIN orders o ON o.customer_id = c.customer_id;

Isso preserva todos os pedidos: (Ana, 101), (Ana, 102), (Ben, 103) e (NULL, 104). A tabela à direita é orders, então o pedido sem cadastro permanece. Chloe e Dev são linhas à esquerda sem correspondência e não permanecem.

Trocar as entradas produz a forma equivalente orders o LEFT JOIN customers c ON o.customer_id = c.customer_id. Manter a mesma lista explícita de seleção produz os mesmos valores. Com SELECT *, a ordem padrão das colunas pode mudar. Usar junções à esquerda em todo o relatório frequentemente facilita acompanhar o lado que deve ser preservado.

Preserve linhas sem correspondência das duas entradas
SELECT c.name, o.order_id
FROM customers c
FULL OUTER JOIN orders o ON o.customer_id = c.customer_id;

O resultado contém (Ana, 101), (Ana, 102), (Ben, 103), (Chloe, NULL), (Dev, NULL) e (NULL, 104). São três pares correspondentes, dois clientes sem correspondência e um pedido sem correspondência: seis linhas. As colunas de cliente são NULL para o pedido sem cadastro 104; as colunas de pedido são NULL para Chloe e Dev.

JunçãoLinhas sem correspondência preservadas
LEFT JOINApenas da entrada à esquerda
RIGHT JOINApenas da entrada à direita
FULL OUTER JOINDas duas entradas

Uma junção completa é útil para a conciliação, como verificar uma lista de estoque de armazém em relação a uma contagem física. Chaves correspondentes aparecem juntas; chaves encontradas em apenas um lado permanecem visíveis. Na consulta da loja, adicionar WHERE c.customer_id IS NULL OR o.order_id IS NULL mantém apenas Chloe, Dev e o pedido 104.

Ao conciliar duas listas do mesmo tipo de chave, qualquer uma das chaves de entrada pode ser NULL na saída. COALESCE(w.sku, k.sku) AS sku seleciona o SKU disponível do apelido w do armazém ou do apelido k da lista de contagem. Uma coluna de chave combinada permite ao relatório identificar registros ausentes de qualquer uma das listas.

Verifique o suporte à sintaxe

PostgreSQL, SQL Server e Oracle oferecem suporte a junções externas à direita e completas. SQLite oferece suporte a ambas a partir da versão 3.39.0, lançada em 2022. Versões anteriores do SQLite as rejeitam. MySQL oferece suporte a junções à direita, mas não tem FULL OUTER JOIN; uma solução alternativa combina resultados de junções à esquerda e à direita com UNION.

Códigos SQL antigos do Oracle podem marcar o lado opcional com (+) em WHERE. Por exemplo, WHERE c.customer_id = o.customer_id(+) preserva os clientes e preenche colunas de pedido ausentes com NULL, como uma junção à esquerda a partir de clientes. O marcador pertence ao lado que pode estar ausente. Use as formas de junção nomeadas LEFT, RIGHT e FULL ao escrever novas consultas.

Principais conclusões

  • Uma junção à direita se torna uma junção à esquerda quando as tabelas trocam de lugar.
  • As linhas de uma junção completa são os pares correspondentes mais as linhas sem correspondência de ambos os lados.
  • Uma junção completa pode revelar diferenças durante a conciliação.
  • O SQLite precisa da versão 3.39.0 ou posterior para junções à direita e completas; o MySQL não tem uma palavra-chave para junção completa.

3.3 Decidir se uma condição pertence a ON ou WHERE

Uma junção externa separa duas decisões: quais pares contam como correspondências e quais linhas de resultado concluídas o relatório mantém. ON toma a primeira decisão. WHERE toma a segunda, depois que as linhas sem correspondência recebem valores NULL.

Preserve todos, mas limite seus pedidos correspondentes

Suponha que um relatório precise de todos os clientes e apenas seus pedidos a partir de 10 de março:

SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.customer_id
 AND o.order_date >= '2026-03-10';

O teste de data faz parte da correspondência. O pedido 101 de Ana é anterior ao limite, mas o pedido 102 atende à condição. O pedido 103 de Ben atende à condição. Chloe e Dev não têm correspondente que atenda à condição, então cada um recebe uma linha preenchida com NULL. O resultado é (Ana, 102), (Ben, 103), (Chloe, NULL) e (Dev, NULL).

Filtre as linhas após a junção

Mova o mesmo teste de data para WHERE:

SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_date >= '2026-03-10';

Agora a junção cria primeiro cinco linhas, incluindo as linhas preenchidas com NULL para Chloe e Dev. A comparação de data é desconhecida para esses valores NULL, então WHERE as remove. Ele também remove o pedido anterior de Ana. Restam apenas (Ana, 102) e (Ben, 103).

A versão com WHERE produz as mesmas linhas correspondentes que uma junção interna com esse filtro de data.

Filtre a tabela preservada intencionalmente

Uma condição do lado esquerdo em ON também não pode remover linhas à esquerda. Considere ON o.customer_id = c.customer_id AND c.city = 'Denver'. Ana pode corresponder aos dois pedidos, Chloe não tem nenhum, e Ben e Dev não atendem à parte da condição referente à cidade em nenhuma correspondência possível. Todos os quatro clientes permanecem, com colunas de pedido NULL para Ben, Chloe e Dev.

Para solicitar apenas clientes de Denver, coloque WHERE c.city = 'Denver' após a condição normal de chave. O resultado é (Ana, 101), (Ana, 102) e (Chloe, NULL). Chloe permanece porque o filtro testa sua própria cidade, não um campo de pedido ausente.

O que a condição deve fazerPosição típica em uma junção à esquerda
Limitar as correspondências elegíveis à direita enquanto preserva todas as linhas à esquerdaON
Limitar quais linhas à esquerda pertencem ao relatórioWHERE
Encontrar linhas cujo correspondente à direita está ausenteWHERE com right_key IS NULL

O teste de antijunção pertence à etapa após a junção porque examina o resultado preenchido com NULL. Junções internas não têm linhas sem correspondência preservadas, então mover um filtro entre ON e WHERE não altera seus pares correspondentes. Ao revisar uma junção externa, leia cada teste WHERE do lado opcional e verifique o que ele faz com uma linha preenchida com NULL.

Principais conclusões

  • ON decide as correspondências; WHERE filtra as linhas de resultado concluídas.
  • Coloque uma restrição do lado direito em ON para preservar linhas à esquerda sem correspondências que atendam à condição.
  • Coloque restrições do relatório referentes ao lado esquerdo em WHERE.
  • Uma comparação do lado direito em WHERE remove linhas preenchidas com NULL quando é desconhecida.
  • O teste IS NULL da antijunção é executado intencionalmente após a junção.
4

Autojunções e junções cruzadas

O mesmo mecanismo de junção pode conectar dois papéis em uma tabela ou gerar todas as combinações de duas tabelas. Consultas de funcionário–gerente precisam de apelidos que mantenham os papéis claros; pares de colegas também precisam de uma regra para pares de uma linha com ela mesma e duplicatas invertidas. Junções cruzadas geram intencionalmente todas as possibilidades, como tamanhos e cores. Prever seu tamanho ajuda você a reconhecer quando essa multiplicação era pretendida e quando falta uma condição.

4.1 Dois papéis para uma tabela

O gerente de um funcionário também é funcionário. Uma autojunção lê a mesma tabela com apelidos diferentes para que uma linha possa representar o funcionário e outra possa representar o gerente. Ela usa a sintaxe comum de junção; não existe uma palavra-chave SELF JOIN.

Nomeie os papéis antes das colunas

Os dados dos funcionários são:

emp_idnamemanager_id
1GraceNULL
2Hassan1
3Iris1
4Jamal2
SELECT e.name AS employee, m.name AS manager
FROM employees e
JOIN employees m ON e.manager_id = m.emp_id;

e fornece a linha do funcionário. Seu manager_id aponta para o emp_id do gerente no papel m. Hassan aponta para 1, então forma um par com Grace; Iris também forma um par com Grace. Jamal aponta para 2 e forma um par com Hassan. O resultado é (Hassan, Grace), (Iris, Grace) e (Jamal, Hassan).

Grace não tem gerente. Seu manager_id é NULL, então a junção interna a exclui. Substituir JOIN por LEFT JOIN adiciona (Grace, NULL), produzindo quatro linhas. Apelidos distintos permitem que o banco de dados diferencie os papéis, embora as duas entradas venham da mesma tabela armazenada.

Faça a pergunta no outro sentido

Para encontrar pessoas que não gerenciam ninguém, comece pelo papel de gerente e procure um funcionário ausente:

SELECT m.name
FROM employees m
LEFT JOIN employees e ON e.manager_id = m.emp_id
WHERE e.emp_id IS NULL;

Isso retorna (Iris) e (Jamal). Grace corresponde a Hassan e Iris; Hassan corresponde a Jamal. Iris e Jamal não têm subordinados diretos. Testar a chave do funcionário após a junção encontra o correspondente ausente deles.

Um terceiro apelido segue mais um nível. employees e JOIN employees m ON e.manager_id = m.emp_id JOIN employees g ON m.manager_id = g.emp_id, selecionando seus nomes, retorna (Jamal, Hassan, Grace). Cada papel adicional segue mais um vínculo. Uma consulta fixa alcança um número fixo de níveis; uma hierarquia de profundidade arbitrária precisa de uma consulta recursiva.

Forme pares de colegas uma vez

A mesma tabela também pode fornecer pares de colegas de trabalho:

SELECT a.name, b.name
FROM employees a
JOIN employees b
  ON a.manager_id = b.manager_id
 AND a.emp_id < b.emp_id;

Hassan e Iris compartilham o gerente 1. O teste de menor que exclui uma pessoa emparelhada consigo mesma e mantém apenas uma ordem de cada par. O resultado é (Hassan, Iris).

Apenas com a igualdade de gerente, o resultado tem cinco linhas: Hassan–Hassan, Hassan–Iris, Iris–Hassan, Iris–Iris e Jamal–Jamal. A chave de gerente NULL de Grace não corresponde a nada, incluindo outro NULL. Substituir < por <> exclui pares de uma pessoa consigo mesma, mas mantém tanto (Hassan, Iris) quanto (Iris, Hassan). Escolha < quando a pergunta precisar de cada par não ordenado uma vez.

Principais conclusões

  • Use apelidos diferentes para os diferentes papéis em uma autojunção.
  • Relacione o manager_id de um funcionário ao emp_id do papel de gerente.
  • Uma autojunção à esquerda pode preservar o topo de uma hierarquia.
  • Cada autojunção adicional segue outro nível fixo.
  • Para pares do mesmo grupo, < remove pares de uma linha com ela mesma e duplicatas invertidas; <> remove apenas os pares de uma linha com ela mesma.

4.2 Todas as combinações possíveis

Uma junção cruzada cria todos os pares de linhas, sem uma condição de correspondência. Isso é útil quando a pergunta pede possibilidades, como todas as combinações de tamanho–cor que uma loja poderia ter em estoque.

Crie a lista de combinações

sizes contém S, M e L. colors contém Red e Blue.

SELECT s.size, c.color
FROM sizes s
CROSS JOIN colors c;

Os seis pares são (S, Red), (S, Blue), (M, Red), (M, Blue), (L, Red) e (L, Blue). Cada tamanho aparece ao lado das duas cores. Essas são as linhas de resultado; sua ordem de exibição não é garantida sem ORDER BY.

Para duas entradas, multiplique suas contagens de linhas. Três tamanhos e duas cores produzem seis linhas. Com uma terceira tabela contendo quatro opções, o resultado tem 24 linhas. Se qualquer entrada estiver vazia, nenhuma combinação completa pode ser formada e o resultado tem zero linhas.

Comece com uma grade completa para relatório

Os registros de vendas mostram apenas combinações que ocorreram. Para mostrar todas as lojas em todos os meses, primeiro forme uma grade com stores CROSS JOIN months. Depois, use uma junção à esquerda para associar os registros de vendas correspondentes:

SELECT s.store_id, m.month, x.total
FROM stores s
CROSS JOIN months m
LEFT JOIN sales x
  ON x.store_id = s.store_id
 AND x.month = m.month;

A grade preserva um par loja–mês mesmo quando não há venda, com NULL em x.total. As duas partes da chave são importantes: comparar apenas a loja também associaria as vendas dessa loja em outros meses. A junção cruzada define quais combinações o relatório deve mostrar, e a junção à esquerda fornece os dados disponíveis sobre elas.

Identifique uma junção cruzada não intencional

FROM customers, orders sem condição de junção forma 16 pares a partir dos quatro clientes e dos quatro pedidos. Ana forma pares com seus próprios pedidos, com o pedido de Ben e com o pedido sem cadastro. Cada cliente faz o mesmo. Isso só é útil se todas as combinações cliente–pedido forem realmente desejadas.

Uma contagem alta de linhas é um indício, mas examine também os pares. Com 1.000 clientes e 1.000 produtos, uma junção cruzada intencional produz 1.000.000 de linhas. Uma junção com uma condição errada, mas seletiva, também pode retornar um resultado menor e incorreto. Compare a contagem e o significado de cada par com a pergunta.

Reconheça formas equivalentes

CROSS JOIN, uma junção por vírgulas sem condição de correspondência e uma junção interna com ON 1 = 1 mantêm todos os pares. SQLite e MySQL também aceitam um JOIN simples sem ON e o tratam como junção cruzada; PostgreSQL exige ON ou USING para uma junção simples. Escreva CROSS JOIN quando todas as combinações forem intencionais.

DISTINCT remove linhas selecionadas idênticas, não relacionamentos incorretos. Se uma junção cruzada acidental emparelhar Ana com o pedido de Ben, esses valores permanecerão como uma linha distinta. Corrija a condição ausente em vez de ocultar parte da saída repetida.

Principais conclusões

  • Uma junção cruzada retorna todas as combinações; multiplique as contagens de linhas das entradas.
  • Uma entrada vazia torna o produto cartesiano vazio.
  • Uma junção cruzada pode criar uma grade completa para uma junção à esquerda posterior.
  • Uma condição de correspondência ausente pode criar uma junção cruzada acidental.
  • DISTINCT não remove pares incorretos.
5

Tabelas associativas e caminhos mais longos

Alguns relatórios precisam percorrer várias tabelas antes que os dados solicitados possam se encontrar. Linhas de matrícula vinculam alunos a cursos, e itens de pedido vinculam pedidos a produtos. Siga uma chave por vez, acompanhe o que cada linha de saída representa e escolha quais vínculos são obrigatórios. Uma junção à esquerda no início de uma cadeia pode perder suas linhas sem correspondência em uma etapa posterior, por isso o caminho inteiro deve preservar os registros pretendidos pelo relatório.

5.1 Seguir um vínculo muitos para muitos

Um aluno pode fazer vários cursos, e um curso pode ter vários alunos. Uma tabela associativa registra esses vínculos muitos para muitos como pares individuais. Ela também é chamada de tabela de junção ou de ligação.

Leia um vínculo por linha

Os dados de exemplo contêm os alunos 1 Mia, 2 Noah e 3 Omar; os cursos 10 Algebra, 20 Biology e 30 Chemistry; e os pares de matrícula (1, 10), (1, 20) e (2, 10).

student_idcourse_id
110
120
210

O aluno 1 aparece duas vezes porque Mia faz dois cursos. O curso 10 aparece duas vezes porque Algebra tem dois alunos. Nenhuma das colunas precisa ser única por si só. O par pode formar uma chave primária composta, PRIMARY KEY (student_id, course_id), impedindo que o mesmo aluno seja matriculado no mesmo curso duas vezes.

Um vínculo pode ter dados próprios. enrolled_on pertence à matrícula porque descreve quando um determinado aluno ingressou em um determinado curso. Da mesma forma, order_items.quantity descreve a quantidade de um determinado produto que pertence a um determinado pedido.

Atravesse a tabela associativa com duas junções
SELECT s.name, c.title
FROM students s
JOIN enrollments e ON e.student_id = s.student_id
JOIN courses c ON c.course_id = e.course_id;

A primeira condição associa as linhas de matrícula de cada aluno. A segunda substitui a referência ao curso de cada matrícula por dados da tabela de cursos. O resultado completo é (Mia, Algebra), (Mia, Biology) e (Noah, Algebra). Cada linha representa uma matrícula.

Não há uma chave que relacione aluno e curso em nenhuma das tabelas das extremidades. Comparar s.student_id = c.course_id compararia identificadores sem relação e ignoraria os dados de matrícula. A tabela associativa fornece o relacionamento.

O mesmo caminho funciona nos dois sentidos. Adicione WHERE c.title = 'Algebra' para obter (Mia, Algebra) e (Noah, Algebra). Adicione WHERE s.name = 'Mia' em vez disso para obter (Mia, Algebra) e (Mia, Biology). Os vínculos permanecem os mesmos; o filtro seleciona quais vínculos respondem à pergunta.

Inclua pessoas ou cursos sem vínculos

Comece pelo lado que deve ser preservado. students s LEFT JOIN enrollments e ON e.student_id = s.student_id preserva Omar com colunas de matrícula NULL. Para mostrar os títulos dos cursos e preservá-lo, a junção posterior de matrículas a cursos também deve preservar a matrícula ausente.

Para encontrar cursos que ninguém faz, use o lado dos cursos e uma antijunção:

SELECT c.title
FROM courses c
LEFT JOIN enrollments e ON e.course_id = c.course_id
WHERE e.student_id IS NULL;

Isso retorna (Chemistry). Em uma matrícula correspondente real, student_id faz parte da chave primária e não pode ser NULL, então o teste identifica o vínculo ausente.

Armazene um relacionamento por linha da tabela associativa. Uma lista de texto como “10,20” em um campo do aluno não pode ser comparada por igualdade aos identificadores individuais de curso 10 e 20. Pares separados permitem que cada condição de junção compare uma referência com uma chave.

Principais conclusões

  • Uma linha da tabela associativa registra um par e pode conter dados sobre esse relacionamento.
  • As duas chaves estrangeiras podem formar uma chave composta que impede pares duplicados.
  • Duas junções conectam as tabelas das extremidades por meio da tabela associativa.
  • Comece pela extremidade que deve ser preservada ao procurar relacionamentos ausentes.

5.2 Um caminho por quatro tabelas

Uma junção mais longa segue a mesma regra de uma junção de duas tabelas: associe a próxima tabela usando uma condição que faça sentido. Antes de escrever a consulta, siga as chaves e decida o que uma linha de resultado deve representar.

Adicione os dados detalhados da loja
product_idnameprice
1Mug8,00
2Pen1,50
3Notebook4,25
4Stapler12,00

Os itens de pedido (order_id, product_id, quantity) são (101, 1, 2), (101, 2, 4), (102, 3, 6), (103, 1, 6), (103, 2, 8) e (104, 2, 10). Cada item vincula um pedido a um produto e registra uma quantidade.

Para a pergunta “O que cada cliente comprou?”, siga customers → orders → order_items → products. As chaves no caminho são identificador do cliente, identificador do pedido e identificador do produto. Quatro tabelas nessa cadeia exigem três vínculos.

Associe uma nova tabela por vez
SELECT c.name, o.order_id, p.name AS product,
       oi.quantity, oi.quantity * p.price AS line_total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
JOIN order_items oi ON oi.order_id = o.order_id
JOIN products p ON p.product_id = oi.product_id
ORDER BY o.order_id, p.product_id;

Cada ON se refere à tabela recém-introduzida e a uma que já está disponível. Os produtos são associados por meio dos itens de pedido, não diretamente por meio dos clientes. O resultado é:

nameorder_idproductquantityline_total
Ana101Mug216,00
Ana101Pen46,00
Ana102Notebook625,50
Ben103Mug648,00
Ben103Pen812,00

A primeira junção exclui o pedido sem cadastro 104 porque sua referência ao cliente é NULL. Os três pedidos restantes contêm cinco itens, então o resultado final tem cinco linhas. Para o pedido 101, duas canecas custam 16,00 e quatro canetas custam 6,00, correspondendo ao total do pedido de 22,00.

Saiba o que uma linha conta

Uma linha de resultado representa um item do pedido. Ana e o pedido 101 aparecem duas vezes porque esse pedido tem dois produtos. Portanto, nomes de clientes repetidos são esperados. Contar essas linhas conta itens, não clientes ou pedidos distintos.

Um filtro pode se referir a qualquer tabela da junção. Adicionar WHERE p.name = 'Pen' antes de ORDER BY mantém (Ana; 101; Pen; 4; 6,00) e (Ben; 103; Pen; 8; 12,00). Nenhum filtro de produto pode recuperar o pedido sem cadastro que já foi excluído no vínculo com clientes.

Mantenha cada vínculo visível

Em uma cadeia de junções internas, a ordem escrita das tabelas pode mudar sem alterar as combinações correspondentes, desde que cada condição se refira apenas a tabelas já introduzidas. Começar pelo assunto do relatório e seguir suas chaves geralmente facilita a leitura.

Uma condição ausente pode multiplicar um resultado intermediário no SQLite ou MySQL, que aceitam um JOIN simples sem ON. PostgreSQL e SQL Server rejeitam essa sintaxe. Uma condição ausente em uma consulta com vírgulas também pode criar todas as combinações nessa etapa.

Às vezes, uma tabela desempenha dois papéis. Um relatório de voos pode juntar airports como dep por dep.code = f.from_code e novamente como arr por arr.code = f.to_code. Apelidos distintos dão aos dados de partida e chegada posições separadas no resultado.

Principais conclusões

  • Adicione uma condição de junção para cada vínculo no caminho de tabelas.
  • Cada ON pode usar a nova tabela e as tabelas já introduzidas.
  • Identifique o que uma linha de saída representa antes de contar ou somar valores.
  • Uma tabela pode aparecer com apelidos diferentes quando o relatório precisa de papéis diferentes.

5.3 Preservar linhas opcionais ao longo de uma cadeia

Uma junção à esquerda preserva linhas em uma etapa. Junções e filtros posteriores ainda atuam sobre o resultado dessa etapa. Para preservar uma linha pai sem correspondência em um caminho mais longo, acompanhe o que acontece com suas colunas preenchidas com NULL em cada estágio.

Veja onde uma linha preservada desaparece
SELECT c.name, o.order_id, oi.product_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
JOIN order_items oi ON oi.order_id = o.order_id;

A primeira etapa cria cinco linhas: os dois pedidos de Ana, o pedido de Ben e uma linha preenchida com NULL para Chloe e outra para Dev. Na etapa seguinte, os valores o.order_id de Chloe e Dev são NULL. Eles não podem satisfazer a igualdade com uma chave de item de pedido, então a junção interna os remove. A consulta retorna cinco linhas de itens de pedido e perde os dois clientes sem pedidos.

Preserve o caminho opcional
SELECT c.name, o.order_id, oi.product_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
LEFT JOIN order_items oi ON oi.order_id = o.order_id;

Agora a segunda junção também preserva essas linhas preenchidas com NULL. O resultado tem (Ana, 101, 1), (Ana, 101, 2), (Ana, 102, 3), (Ben, 103, 1), (Ben, 103, 2), (Chloe, NULL, NULL) e (Dev, NULL, NULL): sete linhas.

Quando junções posteriores dependem de colunas de uma tabela opcional, geralmente precisam continuar sendo junções à esquerda para preservar os correspondentes ausentes. Uma junção interna posterior em colunas de uma tabela obrigatória tem outro papel, então examine a dependência real de cada condição.

Siga a mesma regra por uma tabela associativa
SELECT s.name, c.title
FROM students s
LEFT JOIN enrollments e ON e.student_id = s.student_id
LEFT JOIN courses c ON c.course_id = e.course_id;

Isso retorna (Mia, Algebra), (Mia, Biology), (Noah, Algebra) e (Omar, NULL). Tornar a última junção interna remove Omar porque sua matrícula ausente não pode corresponder a um curso.

Os parênteses oferecem outra forma de expressar o agrupamento: students s LEFT JOIN (enrollments e JOIN courses c ON c.course_id = e.course_id) ON e.student_id = s.student_id. As correspondências matrícula–curso formam o grupo opcional; a junção externa associa esse grupo a cada aluno, preservando Omar.

Verifique filtros posteriores e a direção da junção

Adicionar WHERE c.title = 'Algebra' à consulta de alunos que usa apenas junções à esquerda deixa apenas Mia e Noah em Algebra. A comparação é desconhecida para o título de curso NULL de Omar. Isso responde a “Quem faz Algebra?”, mas não responde mais a “Mostre todos os alunos e seus cursos”. Um teste IS NULL se comporta de forma diferente porque aceita intencionalmente um valor ausente.

Uma junção à direita posterior muda novamente o lado preservado: ela preserva a tabela à direita recém-adicionada, e linhas anteriores sem correspondência podem desaparecer. Coloque primeiro a tabela que deve ser preservada e associe caminhos opcionais com junções à esquerda quando isso expressar o relatório com clareza.

Construa e examine a consulta uma junção por vez. Anote tanto a contagem de linhas quanto as chaves que permanecem. Uma contagem em queda pode revelar linhas sem correspondência perdidas; um salto inesperado pode revelar uma parte ausente da chave. Algumas contagens permanecem inalteradas quando linhas são perdidas e multiplicadas ao mesmo tempo, então examine também chaves representativas.

Principais conclusões

  • Cada junção atua sobre o resultado criado até aquele ponto.
  • Uma junção interna por uma chave NULL de uma tabela opcional remove linhas sem correspondência.
  • Mantenha opcionais os vínculos dependentes posteriores quando suas linhas ausentes precisarem ser preservadas.
  • Uma comparação posterior em WHERE ainda pode remover linhas preservadas por junções à esquerda.
  • Examine a contagem e as chaves que permanecem após cada etapa.
6

Contagens e resultados confiáveis

Valores repetidos frequentemente são uma consequência correta de uma junção, mas podem tornar erradas as contagens e somas de um relatório. Acompanhe um total de pedido enquanto linhas de detalhe o repetem, escolha a identidade correta para contar e distinga o uso útil de DISTINCT de um erro de junção oculto. Depois, verifique um relatório em relação às correspondências previstas, às chaves completas, ao comportamento de NULL e a formatos de chave consistentes antes de confiar em sua saída aparentemente plausível.

6.1 Contar e somar no nível correto

Uma junção pode estar correta enquanto uma agregação sobre seu resultado está errada. A questão principal é o que uma linha representa após a junção. Um valor armazenado uma vez por pedido pode aparecer várias vezes em uma lista de itens de pedido.

Acompanhe um total de pedido repetido

Ana tem o pedido 101 de 22,00 e o pedido 102 de 25,50. Somar os dois pedidos dá 47,50. O pedido 101 tem dois itens, então a junção com order_items repete 22,00 duas vezes; o pedido 102 tem um item. Somar os valores repetidos dá 69,50.

SELECT c.customer_id, c.name, SUM(o.total) AS spent
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;

GROUP BY reúne as linhas de cada cliente, e SUM soma os valores desse grupo. Essa consulta retorna (1; Ana; 47,50) e (2; Ben; 60,00). Adicionar a junção com itens de pedido antes do agrupamento inflaria o valor de Ana para 69,50 e o de Ben para 120,00. Os totais dos dois clientes passariam a 189,50 em vez de 107,50.

Nos quatro pedidos, incluindo o pedido sem cadastro 104, juntar pedidos diretamente a seus itens faz SUM(o.total) retornar 204,50 em vez de 122,50. Essa multiplicação de linhas vem do vínculo um para muitos, não de um erro de sintaxe.

Some os dados no nível em que estão armazenados

Para totais de pedidos, some os pedidos sem adicionar a tabela de detalhes. Para um total de valores de itens, calcule o valor de cada item:

SELECT SUM(oi.quantity * p.price) AS sales
FROM order_items oi
JOIN products p ON p.product_id = oi.product_id;

Os seis valores dos itens são 16,00, 6,00, 25,50, 48,00, 12,00 e 15,00. Eles somam 122,50, o total dos quatro pedidos. Cada produto de quantidade por preço pertence a um item, então cada um é somado uma vez.

Conte correspondências reais

Após juntar clientes a pedidos e itens, Ana ocupa três linhas. COUNT(*) conta esses itens; COUNT(DISTINCT o.order_id) conta seus dois pedidos distintos.

Após apenas uma junção à esquerda de clientes a pedidos, COUNT(*) conta uma linha preenchida com NULL para Chloe e uma para Dev. Em vez disso, conte a chave opcional do pedido:

SELECT c.customer_id, c.name, COUNT(o.order_id) AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;

Isso retorna (1, Ana, 2), (2, Ben, 1), (3, Chloe, 0) e (4, Dev, 0). COUNT(column) ignora valores NULL; COUNT(*) conta linhas.

Dois lados muitos se multiplicam

Se um cliente tem três pedidos e dois chamados, juntar as duas tabelas filhas independentemente a esse cliente cria seis linhas. Cada pedido forma um par com cada chamado. Contagens simples de qualquer uma das chaves filhas passam a seis. Conte chaves filhas distintas para obter três e dois ou totalize as tabelas filhas separadamente.

DISTINCT c.customer_id, c.name é útil para uma lista de clientes sem duplicatas. Manter a chave evita unir clientes diferentes que têm o mesmo nome. Isso não corrige uma condição de junção ausente. SUM(DISTINCT o.total) também não é seguro: ele une dois pedidos separados que por acaso custam o mesmo valor.

Principais conclusões

  • Junções um para muitos repetem valores da linha pai; some um dado no nível em que ele está armazenado.
  • COUNT(*) conta linhas; COUNT(column) ignora valores NULL.
  • COUNT(DISTINCT key) conta identidades distintas que não são NULL após a multiplicação de linhas.
  • Duas junções independentes no lado muitos podem multiplicar uma à outra.
  • SUM(DISTINCT amount) pode unir registros diferentes com valores iguais.
  • Mantenha uma chave de identificação em uma lista de entidades sem duplicatas.

6.2 Verificar correspondências antes de confiar em um relatório

Uma consulta pode ser executada e ainda assim descrever os relacionamentos errados. Antes de usar um resultado de junção, preveja o que deve permanecer, com que frequência cada chave deve aparecer e o que uma linha de resultado deve significar.

Faça uma previsão da contagem de linhas

Se a referência ao cliente em um pedido corresponde a uma chave única de cliente, cada pedido tem no máximo um cliente correspondente. Portanto, uma junção interna retorna no máximo uma linha por pedido. Nos dados da loja, três dos quatro pedidos têm um cliente, então a junção interna cliente–pedido retorna três linhas.

Do lado dos clientes, uma junção à esquerda retorna os três pares correspondentes mais uma linha para Chloe e uma para Dev: cinco linhas. Uma junção cruzada dos quatro clientes com os quatro pedidos produz 16. Essas previsões fornecem verificações diferentes para tipos diferentes de junção; o número de tabelas sozinho não determina a contagem.

Investigue a forma de um resultado errado
SinalO que examinar
Cada linha à esquerda forma um par com cada linha à direitaCondição ausente ou condição sempre verdadeira
Nenhuma correspondência ou entidades sem relação emparelhadasColunas erradas ou valores de chave incompatíveis
Um registro lógico tem vários correspondentesChave incompleta, chave de consulta duplicada ou vínculo um para muitos esperado
Linhas pai sem linhas filhas desaparecemJunção interna ou filtro do lado opcional mais adiante na consulta

Comparar apenas store_id quando os registros são identificados por (store_id, month) mistura meses diferentes. Compare cada componente com AND. Uma consulta que por acaso funciona enquanto uma loja tem um mês pode falhar assim que um segundo mês for carregado.

Separe valores ausentes de chaves ruins

Com igualdade comum, chaves NULL não correspondem, incluindo NULL com NULL. Juntar pedidos a eles mesmos por customer_id produz quatro pares dos dois pedidos de Ana e um do pedido de Ben, totalizando cinco linhas. O pedido sem cadastro não contribui com nenhuma. Uma junção externa é necessária quando uma linha com referência ausente precisa ser preservada.

Valores de consulta duplicados multiplicam apenas as correspondências desses valores. Se um código de país ocorre duas vezes em uma tabela de consulta, cada cliente com esse código recebe duas linhas correspondentes. Códigos que ocorrem uma vez ainda produzem um correspondente. Examine uma tabela de consulta que deveria ser única com:

SELECT code, COUNT(*) AS copies
FROM countries
GROUP BY code
HAVING COUNT(*) > 1;

GROUP BY reúne as linhas de cada código; HAVING mantém grupos cuja contagem é maior que um. Carregar a tabela de consulta inteira duas vezes duplicaria as linhas de cada cliente correspondente.

Examine também os tipos e formatos das chaves. O texto “0042” e o número 42 podem produzir comportamentos diferentes entre bancos de dados: nenhuma correspondência, um erro de tipo ou uma conversão automática. O SQLite pode relacionar uma coluna TEXT contendo “0042” a uma coluna INTEGER contendo 42. Use tipos e formatos de chave consistentes ou uma conversão explícita escolhida para o significado pretendido.

Verifique os requisitos do relatório

Pergunte qual tabela deve preservar todas as linhas. Siga seu caminho completo de chaves e verifique cada condição em relação ao esquema. Decida por que cada vínculo é interno ou externo e depois verifique se cada filtro pertence à etapa de correspondência ou à etapa posterior. Compare as contagens de linhas após cada etapa e examine uma linha correspondente conhecida, uma linha sem correspondência e uma linha com vários correspondentes. Por fim, verifique se cada contagem e soma mede o tipo de registro pretendido.

Principais conclusões

  • Preveja contagens a partir do relacionamento e do tipo de junção.
  • Verifique cada componente de uma chave composta.
  • A igualdade comum nunca considera chaves NULL uma correspondência.
  • Chaves de consulta duplicadas multiplicam as correspondências afetadas.
  • Mantenha as chaves vinculadas com tipos e formatos consistentes.
  • Verifique as identidades que permanecem, além dos totais e contagens de linhas.

Exercícios resolvidos de Junções SQL

6 Lições Interativas

1

Dos vínculos no esquema às linhas juntadas

10 passos
Leia as chaves da loja, preveja os pares correspondentes e deixe clara a origem de cada coluna.
  1. 1
    IntroduçãoComece pela pergunta do relatório

    Um relatório precisa de nomes de clientes ao lado dos totais dos pedidos, mas esses dados estão em tabelas diferentes. Uma junção reúne as linhas relacionadas.

    Primeiro, encontre o vínculo entre as chaves. Depois, imagine os pares que ele permite. Essa ordem ajuda você a prever o resultado antes de escrever SQL: um nome pode se repetir porque tem vários pedidos correspondentes, e uma linha pode desaparecer porque não tem nenhum.

  2. 2
    ExemploLeia as chaves de clientes e pedidos

    Os clientes são 1 Ana, 2 Ben, 3 Chloe e 4 Dev. Os pedidos 101 e 102 se referem ao cliente 1; o pedido 103 se refere ao cliente 2. O pedido 104 é um pedido sem cadastro, com uma referência de cliente NULL.

    O vínculo é orders.customer_id → customers.customer_id. O número do pedido identifica uma compra, enquanto a referência ao cliente identifica seu dono. Comparar esses dois tipos diferentes de identificador não expressaria a quem o pedido pertence.

  3. 3
    ExplicaçãoColoque a referência no lado muitos

    Um cliente pode fazer vários pedidos. Cada pedido armazena uma referência de cliente, então orders é o lado muitos do vínculo.

    Em um vínculo um para um, essa referência também é única. Em vínculos muitos para muitos, como alunos que fazem cursos, uma tabela associativa registra os pares. Essas estruturas indicam qual caminho um relatório deve seguir e onde são possíveis vários correspondentes.

  4. 4
    DesafioEncontre o caminho que falta

    Você precisa dos produtos que cada cliente comprou. O esquema vincula customers a orders, orders a order_items e order_items a products. É possível pular order_items e comparar o identificador do pedido diretamente com o identificador do produto?

    ---reveal---

    Não. Esses identificadores identificam coisas diferentes. Siga customers → orders → order_items → products. Cada linha de item do pedido registra um produto em um determinado pedido, fornecendo o vínculo que falta à comparação direta.

  5. 5
    ExemploForme os primeiros pares

    Aplique o.customer_id = c.customer_id. O pedido 101 corresponde a Ana porque os dois valores de cliente são 1. O pedido 102 forma outro par com Ana, e o pedido 103 corresponde a Ben.

    Os pares resultantes são (Ana, 101), (Ana, 102) e (Ben, 103). Chloe e Dev não têm correspondentes. O pedido sem cadastro 104 tem uma chave de cliente NULL, então sua condição de igualdade é desconhecida e não produz correspondência.

  6. 6
    Ideia-chaveUma linha para cada correspondência

    Imagine uma linha traçada entre cada linha de cliente e cada linha de pedido que corresponde a ela. Cada linha traçada se torna uma linha de resultado. Ana tem duas linhas traçadas, então seu nome aparece duas vezes.

    Essa representação também funciona quando as chaves se repetem dos dois lados: duas linhas à esquerda e três à direita com uma mesma chave criam seis linhas traçadas. Círculos sobrepostos não conseguem mostrar esses pares individuais nem explicar como uma junção pode ter mais linhas que qualquer uma das entradas.

  7. 7
    DicaIndique de onde vem uma coluna

    Dê apelidos às referências de tabela, como customers c e orders o. Escreva c.name para o nome do cliente e o.total para o total do pedido.

    As duas entradas têm customer_id. Com JOIN ... ON, selecionar apenas esse nome é ambíguo; qualifique-o como c.customer_id ou o.customer_id. SELECT * inclui todas as sete colunas de entrada, incluindo as duas cópias da chave. Selecionar apenas as colunas necessárias torna o relatório mais estreito.

  8. 8
    ExplicaçãoA correspondência vem antes da filtragem

    Leia a ordem lógica como junções, depois WHERE, depois SELECT e depois ORDER BY. Um filtro pode usar uma coluna de uma tabela da junção que o relatório não exibe.

    Por exemplo, filtrar os pares cliente–pedido por c.city = 'Denver' mantém os dois pedidos de Ana. Chloe também mora em Denver, mas uma junção interna não produziu nenhuma linha para ela. Um filtro posterior não pode recuperar uma linha excluída durante a correspondência.

  9. 9
    DesafioPreveja um resultado com chave repetida

    Uma tabela de inscrições tem duas linhas com a chave de local 8. Uma tabela de consulta de locais tem acidentalmente três linhas com a chave 8. Todas as outras chaves estão ausentes. Quantas linhas a junção interna por igualdade entre elas retorna, e selecionar apenas a chave altera essa contagem?

    ---reveal---

    São retornadas seis linhas: cada inscrição corresponde às três linhas da tabela de consulta. Selecionar apenas a chave reduz a largura de cada linha, mas mantém seis linhas, a menos que uma operação separada, como DISTINCT, remova valores selecionados repetidos.

  10. 10
    RecapitulaçãoLeia o relacionamento e depois as linhas

    Encontre o caminho de chaves antes de escolher as colunas de saída. Vínculos um para muitos podem repetir valores da linha pai; uma tabela associativa contém um vínculo muitos para muitos.

    Para cada par, pergunte se a condição é verdadeira. Depois, verifique quantos correspondentes cada linha tem. Use apelidos para distinguir as origens das colunas e mantenha a correspondência separada da filtragem e da ordenação posteriores ao explicar o resultado.

2

Criar e interpretar junções internas

11 passos
Escreva uma consulta completa de correspondência e depois compare condições abreviadas e de intervalo.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoExija um correspondente dos dois lados
  2. 2
    ExemploEscreva a condição de chave
  3. 3
    ExemploLeia as três linhas de saída
  4. 4
    DesafioAdicione um filtro de clientes
  5. 5
    DicaCompare a identidade completa
  6. 6
    ExplicaçãoUse uma abreviação para nomes compartilhados
  7. 7
    DesafioObserve o que NATURAL altera
  8. 8
    ConexãoLeia uma junção antiga por vírgulas
  9. 9
    ExemploRelacione preços a faixas
  10. 10
    DesafioPreveja uma sobreposição e uma lacuna
  11. 11
    RecapitulaçãoLeia a condição por trás da sintaxe
3

Preservar linhas sem correspondência sem perdê-las em filtros

14 passos
Escolha o lado preservado e acompanhe ON e WHERE nos resultados de junções externas.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoDecida quais registros devem permanecer
  2. 2
    ExemploPreserve todos os clientes
  3. 3
    DesafioMude o lado que deve ser preservado
  4. 4
    DicaTeste a chave do correspondente ausente
  5. 5
    ExplicaçãoLeia uma junção à direita como uma junção à esquerda invertida
  6. 6
    ExemploPreserve registros sem correspondência dos dois lados
  7. 7
    DesafioConcilie duas novas listas de chaves
  8. 8
    DicaVerifique o suporte a junções externas
  9. 9
    ExemploRestrinja os pedidos correspondentes em ON
  10. 10
    ExemploMova o teste de data para WHERE
  11. 11
    DesafioFiltre a tabela à esquerda intencionalmente
  12. 12
    ConexãoDecida o que significa um zero exibido
  13. 13
    DesafioPreserve todos com atividade recente
  14. 14
    RecapitulaçãoMantenha correspondência e filtragem separadas
4

Acompanhar gerentes e criar combinações

11 passos
Use apelidos de papel para autojunções e depois distinga produtos cartesianos intencionais e acidentais.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoEscolha papéis ou possibilidades
  2. 2
    ExemploLeia as relações de subordinação
  3. 3
    DesafioPreserve a pessoa no topo
  4. 4
    ConexãoSuba mais um nível
  5. 5
    ExemploForme pares de colegas uma vez
  6. 6
    ExemploCrie seis possibilidades de camisa
  7. 7
    DesafioPreveja o efeito de outra entrada
  8. 8
    Ideia-chaveCrie uma grade completa para relatório
  9. 9
    DicaCorrija a condição ausente
  10. 10
    DesafioRelacione regras de pares ao tamanho do produto
  11. 11
    RecapitulaçãoDê a cada formação de pares um propósito claro
5

Seguir uma tabela associativa e preservar um caminho mais longo

14 passos
Siga matrículas e itens de compra e depois preserve correspondentes ausentes ao longo de vínculos dependentes.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoPlaneje o caminho até os dados
  2. 2
    ExemploLeia os vínculos de matrícula
  3. 3
    ExemploAtravesse a tabela associativa em duas etapas
  4. 4
    DesafioEncontre um curso sem alunos
  5. 5
    ExplicaçãoEstenda o caminho da loja
  6. 6
    ExemploExpanda o pedido 101 em itens
  7. 7
    ExemploLeia as demais linhas de compra
  8. 8
    DesafioEscolha o vínculo com produtos
  9. 9
    ExemploVeja uma junção posterior remover clientes
  10. 10
    ExemploLeve a linha ausente adiante
  11. 11
    DesafioPreserve o aluno sem matrícula
  12. 12
    ConexãoCrie um grupo opcional explicitamente
  13. 13
    DesafioVerifique o filtro do relatório concluído
  14. 14
    RecapitulaçãoExamine o caminho inteiro
6

Corrigir totais inflados e verificar o resultado

12 passos
Escolha o registro correto para contar ou somar e depois diagnostique problemas de chave e contagem de linhas.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoNomeie o que está sendo medido
  2. 2
    ExemploObserve a repetição de um total de pedido
  3. 3
    DicaSome um dado em seu próprio nível
  4. 4
    DesafioDescarte uma correção baseada no valor
  5. 5
    ExemploConte uma identidade ou uma linha de preenchimento
  6. 6
    Ideia-chaveDuas listas filhas se multiplicam
  7. 7
    ExplicaçãoPreveja a dimensão antes de executar
  8. 8
    DesafioLocalize uma chave incompleta
  9. 9
    DicaVerifique a tabela de consulta e o formato da chave
  10. 10
    ExemploNão relacione chaves ausentes por igualdade
  11. 11
    DesafioEscolha uma medida correta para o relatório
  12. 12
    RecapitulaçãoVerifique o significado e também as contagens

Questões de Junções SQL

50 Questões de Prática em 5 conjuntos

Conjunto 1: Interpretar relacionamentos e escolher linhas correspondentes10 Questões de Prática

Questão 1 de 10

Um associado de biblioteca pode ter vários empréstimos, e cada empréstimo pertence a um associado. Onde a chave estrangeira do associado deve ser armazenada?
  1. Na tabela de associados
  2. Na tabela de empréstimos
  3. Nas duas tabelas
  4. Em uma tabela separada
Mostrar respostaOcultar resposta
Resposta: B
Cada empréstimo precisa identificar seu associado, então a chave estrangeira pertence a loans, o lado muitos. Um associado pode ser referenciado por várias linhas de empréstimo. Colocar uma referência de empréstimo em members não representaria todos os empréstimos que esse associado pode ter.

Questão 2 de 10

Duas linhas da tabela a têm a chave 7. Três linhas da tabela b têm a chave 7. Essas são as únicas linhas. Quantas linhas a JOIN b ON a.k = b.k retorna?
  1. 2
  2. 3
  3. 5
  4. 6
Mostrar respostaOcultar resposta
Resposta: D
Cada uma das duas linhas à esquerda corresponde às três linhas à direita, produzindo seis pares distintos de linhas. Uma junção interna mantém todos os pares correspondentes, mesmo quando os valores de chave se repetem. Contar apenas as três linhas à direita ignoraria que cada uma tem duas correspondentes à esquerda.

Questão 3 de 10

rentals.customer_ref se refere a customers.customer_id. Aluguéis também têm seu próprio rental_id. Qual condição ON vincula cada aluguel r a seu cliente c?
  1. r.customer_ref = c.customer_id
  2. r.rental_id = c.customer_id
  3. r.customer_ref = r.rental_id
  4. c.customer_id = c.customer_id
Mostrar respostaOcultar resposta
Resposta: A
A chave estrangeira customer_ref identifica o cliente associado ao aluguel, então deve ser comparada com a chave do cliente. O identificador de aluguel identifica um aluguel e expressa outro significado. Identificadores numéricos semelhantes não são suficientes para estabelecer um vínculo.

Questão 4 de 10

As tabelas a e b contêm, cada uma, account_id e region. Uma junção natural antes compartilhava apenas account_id; region acabou de ser adicionada a b. Por que um par que antes correspondia pode desaparecer?
  1. Suas regiões coincidem, mas seus identificadores de conta diferem.
  2. Adicionar uma coluna compartilhada faz todos os pares corresponderem.
  3. Seus identificadores de conta coincidem, mas suas regiões diferem.
  4. A nova coluna faz os identificadores compartilhados aparecerem duas vezes.
Mostrar respostaOcultar resposta
Resposta: C
NATURAL JOIN compara todos os nomes de coluna compartilhados, então region agora se junta a account_id como igualdade obrigatória. Um par com identificadores de conta iguais, mas regiões diferentes, deixa de corresponder. A junção não mantém um par apenas porque uma coluna compartilhada coincide.

Questão 5 de 10

As equipes são (1, North) e (2, South). As partidas (match_id, team_id) são (81, 1) e (82, 1). Quais nomes aparecem em um LEFT JOIN a partir das equipes com as partidas, antes da filtragem?
  1. North uma vez; South uma vez
  2. North duas vezes; South uma vez
  3. North duas vezes; South nenhuma
  4. North duas vezes; South duas vezes
Mostrar respostaOcultar resposta
Resposta: B
North tem duas linhas de partida correspondentes, então aparece duas vezes. South não tem correspondência, mas a junção à esquerda o preserva uma vez com colunas de partida NULL. Contar uma linha por equipe deixaria de considerar a linha adicional produzida pela segunda partida de North.

Questão 6 de 10

A lista A tem as chaves únicas 2 e 5. A lista B tem as chaves únicas 5 e 8. Quais pares resultam de um FULL OUTER JOIN por igualdade de chaves?
  1. (2, NULL), (5, 5)
  2. (5, 5), (NULL, 8)
  3. (2, NULL), (5, 5), (NULL, 8)
  4. (2, 2), (5, 5), (8, 8)
Mostrar respostaOcultar resposta
Resposta: C
A chave 5 corresponde entre as duas entradas. A chave 2 existe apenas em A, e a chave 8 existe apenas em B, então cada uma permanece com NULL no lugar do correspondente ausente. Preencher as duas colunas com cada chave sem correspondência inventaria valores de uma linha que nunca esteve presente naquele lado.

Questão 7 de 10

Os funcionários são (id, manager_id): (10, NULL), (11, 10), (12, 10). Uma autojunção usa a.manager_id = b.manager_id AND a.id < b.id. Qual par de identificadores é retornado?
  1. (11, 12)
  2. (10, 11)
  3. (11, 11)
  4. (12, 11)
Mostrar respostaOcultar resposta
Resposta: A
Os funcionários 11 e 12 têm o mesmo gerente, 10, e 11 é menor que 12. A condição de menor que exclui pares de uma pessoa consigo mesma e o par invertido. O funcionário 10 tem um identificador de gerente NULL, então ele não pode ser igual ao identificador de gerente do funcionário 11 ou 12.

Questão 8 de 10

Um estúdio lista 4 salas e 3 horários de sessão. Quantas linhas um CROSS JOIN das listas produz?
  1. 7
  2. 4
  3. 3
  4. 12
Mostrar respostaOcultar resposta
Resposta: D
Cada uma das quatro salas forma um par com cada um dos três horários, produzindo doze combinações. Somar quatro e três contaria entradas, não pares sala–horário. Nenhuma condição de correspondência limita as combinações em uma junção cruzada.

Questão 9 de 10

authors(author_id) e books(book_id) são vinculadas por book_authors(author_id, book_id). Qual caminho encontra os livros de um autor?
  1. authors → books por IDs iguais
  2. authors → books com CROSS JOIN
  3. book_authors → authors por book_id
  4. authors → book_authors → books
Mostrar respostaOcultar resposta
Resposta: D
A tabela associativa registra qual autor pertence a qual livro. Junte authors a book_authors pelo identificador do autor e book_authors a books pelo identificador do livro. Igualar diretamente os identificadores das duas extremidades compara tipos diferentes de identificador e ignora os relacionamentos de autoria armazenados.

Questão 10 de 10

sales(store_id, month) tem (6, March) e (6, April). targets(store_id, month) tem os mesmos dois pares, cada um uma vez. Uma consulta faz a junção apenas pelo identificador da loja e retorna quatro linhas. Qual correção produz uma meta por venda?
  1. Usar DISTINCT apenas no identificador da loja.
  2. Adicionar a igualdade das duas colunas de mês a ON.
  3. Substituir a junção interna por uma junção à esquerda.
  4. Manter apenas as duas primeiras linhas com LIMIT 2.
Mostrar respostaOcultar resposta
Resposta: B
O identificador da loja sozinho permite que a venda de cada mês corresponda aos dois meses de meta, criando quatro pares. Comparar também o mês deixa apenas março–março e abril–abril. Uma junção à esquerda ainda criaria as quatro correspondências, pois preservar linhas não completa uma chave incompleta.
Conjunto 2: Preservar linhas sem correspondência e seguir caminhos de tabelas10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Cada ativo pode ter no máximo uma etiqueta ativa, e cada etiqueta pertence a no máximo um ativo. Qual relacionamento descreve as duas tabelas?
  1. Um para muitos
  2. Muitos para muitos
  3. Um para um
  4. Todos os pares
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

invoices contém (invoice_id, client_id): (301, 9), (302, NULL), (303, 12). clients tem os identificadores únicos 9 e 12. Quais identificadores de fatura permanecem em uma junção interna pelo identificador do cliente?
  1. 301 e 303
  2. 301, 302 e 303
  3. Apenas 302
  4. Apenas 301
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma mesa pode ter várias reservas. Identificadores de reserva não podem ser NULL, mas note pode ser NULL. Após desks LEFT JOIN reservations, qual teste WHERE encontra apenas mesas sem reserva?
  1. r.note IS NULL
  2. r.reservation_id = NULL
  3. r.note IS NOT NULL
  4. r.reservation_id IS NULL
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Um relatório deve mostrar todos os departamentos e associar apenas funcionários ativos. Ele começa com departments d LEFT JOIN employees e ON e.department_id = d.department_id. Onde deve ficar e.active = 1?
  1. Como uma condição em WHERE
  2. Como uma condição AND adicional em ON
  3. Como a expressão de ORDER BY
  4. Como substituição da comparação de chaves
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um CROSS JOIN combina uma tabela com 8 linhas e uma tabela vazia. Quantas linhas são retornadas?
  1. 8
  2. 1
  3. 9
  4. 0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

memberships(member_id, club_id) registra a entrada de um associado em um clube. Onde deve ficar joined_on, a data dessa associação específica?
  1. Em memberships
  2. Em members
  3. Em clubs
  4. Em uma lista de clubes separada por vírgulas
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um relatório segue clients → invoices → lines → services. Cada seta é um vínculo de chave, e cada linha de serviço é única pelo identificador do serviço. O que uma linha de detalhe do resultado representa quando todos os vínculos têm correspondência?
  1. Um cliente
  2. Uma fatura
  3. Um item de fatura
  4. Um serviço no catálogo
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

As filiais são 1 e 2. A filial 1 tem um trabalho com duas linhas de tarefa; a filial 2 não tem trabalhos. Uma cadeia usa branches LEFT JOIN jobs e depois INNER JOIN tasks pela chave do trabalho. Como tornar a junção com tarefas uma junção LEFT altera a contagem de linhas?
  1. Permanece em 2.
  2. Aumenta de 2 para 3.
  3. Aumenta de 2 para 4.
  4. Diminui de 3 para 2.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Um projeto tem duas faturas, cada uma de 40,00. A primeira fatura tem dois itens e a segunda tem três. Após juntar faturas a itens, quais são os valores de SUM(total) e SUM(DISTINCT total)?
  1. 80,00 e 80,00
  2. 200,00 e 80,00
  3. 200,00 e 40,00
  4. 80,00 e 40,00
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma tabela de consulta de regiões deve ter uma linha por code. Alguns clientes resultantes da junção aparecem duas vezes. Qual consulta de diagnóstico encontra códigos de consulta repetidos?
  1. SELECT code, COUNT(*) FROM regions GROUP BY code HAVING COUNT(*) > 1;
  2. SELECT DISTINCT code FROM regions;
  3. SELECT code, COUNT(*) FROM regions GROUP BY code HAVING COUNT(*) = 1;
  4. SELECT code FROM regions WHERE code IS NULL;
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 3: Acompanhar filtros, pares e valores repetidos10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma junção com ON combina uma tabela de 4 colunas com uma tabela de 3 colunas. Qual é a largura de SELECT * antes de remover qualquer coluna?
  1. 4 colunas
  2. 3 colunas
  3. 12 colunas
  4. 7 colunas
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma cobrança de 25,00 é relacionada a faixas usando BETWEEN low AND high. As faixas são (0.00, 25.00) e (25.00, 50.00). Quantas linhas de faixa correspondentes a cobrança produz?
  1. 0
  2. 1
  3. 2
  4. 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma consulta usa suppliers s RIGHT JOIN deliveries d ON d.supplier_id = s.supplier_id e seleciona explicitamente s.name, d.delivery_id. Como ela pode preservar os mesmos pares com LEFT JOIN?
  1. suppliers s LEFT JOIN deliveries d ON d.supplier_id = s.supplier_id
  2. deliveries d LEFT JOIN suppliers s ON d.supplier_id = s.supplier_id
  3. deliveries d JOIN suppliers s ON d.supplier_id = s.supplier_id
  4. suppliers s FULL JOIN deliveries d ON d.supplier_id = s.supplier_id
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

As lojas A e B são preservadas em uma junção à esquerda com visitas. A tem uma visita antes de uma data limite; B não tem nenhuma. ON mantém apenas visitas na data limite ou depois dela. Se essa restrição for movida para WHERE, sem outras alterações, quais lojas permanecem?
  1. Nem A nem B
  2. Apenas A
  3. Apenas B
  4. Tanto A quanto B
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Três funcionários têm identificadores distintos 21, 22 e 23, todos com identificador de gerente 5. Uma autojunção relaciona identificadores de gerente iguais e identificadores de funcionário diferentes usando <>. Quantas linhas são retornadas e quantas < retornaria?
  1. 3 com <>; 3 com <
  2. 6 com <>; 3 com <
  3. 9 com <>; 6 com <
  4. 6 com <>; 6 com <
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Uma linha de voo tem from_code e to_code, ambos se referindo a airports.code. Como um relatório deve obter os dois nomes de aeroportos?
  1. Juntar airports uma vez por from_code e reutilizar o nome para a chegada.
  2. Juntar airports uma vez pelas duas igualdades de código com AND.
  3. Fazer uma junção cruzada com airports e filtrar apenas por from_code.
  4. Juntar airports duas vezes com apelidos para partida e chegada.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Todos os técnicos devem aparecer com suas atribuições e locais opcionais. A consulta junta atribuições à esquerda e depois junta locais por uma junção interna usando o identificador de local da atribuição. Por que técnicos sem atribuição desaparecem?
  1. Suas chaves de atribuição NULL não podem corresponder na junção interna com locais.
  2. Uma junção à esquerda pode preservar apenas um técnico sem atribuição.
  3. Selecionar uma coluna de local remove todas as linhas sem correspondência.
  4. O apelido de local oculta a chave primária do técnico.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma equipe não tem tarefas. Após teams LEFT JOIN tasks e o agrupamento por equipe, o que COUNT(t.task_id) retorna se identificadores de tarefa não podem ser NULL?
  1. 1
  2. NULL
  3. 0
  4. O número de equipes
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Um escritor tem 2 artigos e 3 prêmios, cada um vinculado independentemente a ele. Uma consulta junta as duas tabelas filhas por uma junção interna pelo identificador do escritor e agrupa por escritor. Quais são os valores de COUNT(article_id) e COUNT(DISTINCT award_id)?
  1. 2 e 3
  2. 6 e 6
  3. 6 e 3
  4. 3 e 2
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um relatório começa com shipments s LEFT JOIN carriers c por uma chave de transportadora correspondente. Uma remessa não tem transportadora correspondente, e uma transportadora não tem remessas. Qual registro sem correspondência é preservado?
  1. Apenas a transportadora
  2. Apenas a remessa
  3. Ambos os registros sem correspondência
  4. Nenhum dos registros sem correspondência
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 4: Diagnosticar vínculos incompletos e linhas ausentes10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

workers.supervisor_ref se refere a workers.worker_id. Trabalhadores também têm uma coluna name. O que deve vincular o apelido de trabalhador w ao apelido de supervisor s?
  1. w.supervisor_ref = s.worker_id
  2. w.worker_id = s.supervisor_ref
  3. w.name = s.name
  4. w.worker_id = s.worker_id
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma condição de junção é verdadeira para 4 pares candidatos de linhas, falsa para 3 e desconhecida para 2. Quantas linhas a junção interna retorna?
  1. 6
  2. 4
  3. 7
  4. 9
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma consulta junta pagamentos p a contas a por uma junção interna pelo identificador da conta. Ela seleciona apenas a.name, p.amount. O identificador da conta também precisa ser selecionado para a junção funcionar?
  1. Sim; as duas colunas de identificador da conta devem ser selecionadas.
  2. Sim; pelo menos uma coluna de identificador da conta deve ser selecionada.
  3. Não; SELECT adiciona automaticamente os dois identificadores de conta.
  4. Não; ON pode usar colunas ausentes de SELECT.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

As tabelas a(id, label) e b(id, label) têm as linhas (1, red), (2, blue) e (1, red), (2, green), respectivamente. Quantas linhas são retornadas com JOIN ... USING (id) e com NATURAL JOIN?
  1. 1 com USING; 1 com NATURAL
  2. 2 com USING; 2 com NATURAL
  3. 2 com USING; 1 com NATURAL
  4. 4 com USING; 2 com NATURAL
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

As regiões East e West têm um escritório cada. Um LEFT JOIN que preserva todas as regiões inclui AND r.name = 'East' em ON. Quais linhas aparecem ao selecionar região e escritório?
  1. East com seu escritório; West com NULL
  2. East com seu escritório; West ausente
  3. East com seu escritório; West com seu escritório
  4. East com NULL; West com NULL
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Os trabalhadores são (id, boss_id): (31, NULL), (32, 31), (33, 32), (34, 32). Quais triplas de identificadores são retornadas por junções internas em e.boss_id = m.id e m.boss_id = g.id?
  1. Apenas (32, 31, NULL)
  2. (31, 32, 33) e (31, 32, 34)
  3. (32, 31, NULL), (33, 32, 31), (34, 32, 31)
  4. (33, 32, 31) e (34, 32, 31)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

customers → orders → order_lines → products é um caminho de chaves. Uma junção interna de quatro tabelas usa todos os vínculos. Por que um identificador de pedido pode aparecer em várias linhas mesmo se cada chave primária for única?
  1. A chave primária do produto deve estar duplicada.
  2. Toda junção retorna todos os produtos para cada pedido.
  3. O pedido tem várias linhas de item correspondentes.
  4. Chaves únicas impedem relacionamentos um para muitos.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

As zonas A e B devem aparecer. A tem uma reserva vinculada a um serviço real; B não tem reservas. A consulta junta reservas e serviços à esquerda e depois adiciona WHERE service.category = 'Repair'. O serviço de A é Repair. O que permanece?
  1. A com seu serviço; B com NULL
  2. A com seu serviço; B desaparece
  3. As duas zonas com campos de serviço NULL
  4. B com NULL; A desaparece
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Dois assinantes se chamam Lee, com identificadores 41 e 42. O primeiro tem dois pagamentos e o segundo tem um. Após uma junção interna com pagamentos, quantas linhas SELECT DISTINCT name e SELECT DISTINCT subscriber_id, name retornam?
  1. 2 e 2
  2. 1 e 3
  3. 3 e 2
  4. 1 e 2
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma tabela de consulta tem o código X duas vezes e o código Y uma vez. Um evento referencia X e dois eventos referenciam Y. Quantas linhas a junção interna entre eles produz?
  1. 4
  2. 3
  3. 5
  4. 6
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 5: Verificar relatórios completos sob condições alteradas10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

A tabela A tem linhas com as chaves 1, 1, 2. A tabela B tem linhas com as chaves 1, 1, 1, 3. Quantas linhas uma junção interna por igualdade retorna?
  1. 3
  2. 7
  3. 6
  4. 12
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma taxa de 9,50 é juntada por uma junção interna às faixas [0.00, 9.00], [10.00, 20.00] e [8.00, 12.00] usando testes inclusivos BETWEEN. Se a terceira faixa for removida, como a saída dessa taxa muda?
  1. De duas linhas para uma linha
  2. De uma linha para uma linha
  3. De três linhas para duas linhas
  4. De uma linha para zero linhas
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

A lista A contém as chaves 4, 4, 9; a lista B contém as chaves 4, 4, 12. Uma junção completa por igualdade seleciona as duas colunas de chave. Quantas linhas são retornadas e quantas permanecem após WHERE a.k IS NULL OR b.k IS NULL?
  1. 4 no total; 2 sem correspondência
  2. 6 no total; 2 sem correspondência
  3. 6 no total; 4 sem correspondência
  4. 9 no total; 2 sem correspondência
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Os clientes P e Q têm, cada um, um pedido antigo e nenhum pedido recente; R não tem pedidos. Um LEFT JOIN apenas pela chave é seguido por WHERE o.date >= '2026-09-01' OR o.order_id IS NULL. Quais clientes permanecem?
  1. Apenas R
  2. P, Q e R
  3. Apenas P e Q
  4. Nenhum cliente
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um CROSS JOIN combina 2 modalidades, 5 regiões e 4 meses. Quantas combinações ele produz?
  1. 11
  2. 20
  3. 40
  4. 10
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Os associados são 7, 8 e 9; os clubes são 50 e 60. Os pares de associação são (7,50), (7,60) e (8,50). Uma consulta junta associados a associações à esquerda e depois a clubes. Qual é a contagem total de linhas e qual é o valor de clube do associado 9?
  1. 3 linhas; NULL
  2. 4 linhas; NULL
  3. 4 linhas; 60
  4. 6 linhas; NULL
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Os grupos G e H devem aparecer. G tem uma inscrição vinculada a uma turma válida; H não tem nenhuma. Compare groups LEFT JOIN signups JOIN classes com groups LEFT JOIN (signups JOIN classes), usando as chaves relevantes. O que acontece com H?
  1. Apenas o caminho opcional agrupado preserva H.
  2. As duas formas preservam H.
  3. Apenas o caminho não agrupado preserva H.
  4. Nenhuma das formas preserva H.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um cliente tem as faturas 501 de 18,00 e 502 de 27,00. A fatura 501 tem 3 itens; a fatura 502 tem 2. O relatório precisa do valor total das faturas e do número de faturas. Qual resultado deve apresentar?
  1. 108,00 e 5
  2. 45,00 e 5
  3. 108,00 e 2
  4. 45,00 e 2
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma tabela armazena um identificador em uma coluna TEXT como “0064”; outra armazena 64 em uma coluna INTEGER. O que você deve verificar antes de confiar na junção por igualdade entre elas em diferentes bancos de dados?
  1. Apenas se as duas tabelas têm contagens de linhas iguais
  2. Apenas se as duas colunas compartilham o mesmo nome
  3. Os tipos, formatos e comportamento de conversão das chaves
  4. Se DISTINCT pode remover todas as linhas sem correspondência
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma linha pai tem 2 contas e 4 casos, vinculados independentemente pelo identificador da linha pai. Uma junção interna com as duas tabelas filhas agrupa por linha pai. Quais são os valores de COUNT(*), COUNT(DISTINCT bill_id) e COUNT(DISTINCT case_id)?
  1. 6, 2 e 4
  2. 8, 2 e 4
  3. 8, 8 e 8
  4. 4, 2 e 4
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

58 Termos-Chave, cada um com sua definição

A

AND em uma condição de junção
AND em uma condição de junção exige que todos os testes que a compõem sejam verdadeiros para que o par candidato conte como correspondência.
Comparar loja e mês impede que a linha de abril de uma loja seja juntada a seus valores de março.
Antijunção
Uma antijunção retorna linhas sem correspondente, que podem ser encontradas por uma junção à esquerda seguida de um teste de chave ausente à direita.
Junte produtos a itens de pedido à esquerda e teste a chave de item ausente para encontrar produtos não vendidos, como um grampeador.
Apelido de tabela
Um apelido de tabela é um nome curto atribuído a uma referência de tabela para manter claros seu papel e as referências a suas colunas em uma consulta.
Em FROM customers c, o apelido c permite que a consulta se refira ao nome do cliente como c.name.
Atributo do relacionamento
Um atributo do relacionamento é um dado sobre um vínculo específico entre registros, então pertence à linha que representa esse vínculo.
A quantidade é armazenada em uma linha de item do pedido porque o mesmo produto pode ser comprado em quantidades diferentes em pedidos diferentes.
Autojunção
Uma autojunção junta uma tabela a ela mesma com apelidos separados para que suas linhas possam desempenhar papéis diferentes ou ser comparadas entre si.
O apelido de funcionário fornece manager_id, e o apelido de gerente fornece o emp_id correspondente.

C

Cadeia de junções
Uma cadeia de junções associa várias tabelas em uma consulta, com cada nova junção atuando sobre as linhas criadas pelas junções anteriores.
Quando uma junção cliente–pedido cria três pares e esses pedidos têm cinco itens, juntar os itens de pedido os expande em cinco linhas de detalhe.
Cadeia de junções internas e externas
Uma cadeia de junções internas e externas combina os dois tipos de junção, exigindo que cada etapa seja verificada quanto às linhas anteriores que pode remover.
Uma junção à esquerda com pedidos seguida de uma junção interna com itens de pedido remove clientes cuja chave de pedido é NULL.
Caminho de junção
Um caminho de junção é uma sequência de vínculos significativos que conecta as tabelas necessárias para uma consulta, com uma condição para cada vínculo.
O relatório de compras segue de clientes a pedidos, depois a itens de pedido e a produtos para chegar aos nomes dos produtos.
Chave composta
Uma chave composta identifica um registro usando várias colunas juntas; relacionar uma referência a ela exige cada componente da chave.
O par aluno–curso impede matrículas duplicadas, embora nem o identificador do aluno nem o do curso seja único sozinho.
Chave de consulta duplicada
Uma chave de consulta duplicada é um valor repetido em um lado que deveria ser único, fornecendo correspondentes extras às linhas de entrada relacionadas.
Se um código de país aparece duas vezes, cada cliente com esse código produz duas correspondências na junção com a tabela de consulta.
Chave estrangeira
Uma chave estrangeira é uma coluna ou um grupo de colunas que se refere a uma chave primária ou única na mesma tabela ou em outra tabela.
Vários pedidos podem conter o identificador de cliente 1, vinculando cada um deles à única linha de cliente com esse identificador.
Chave primária
Uma chave primária é uma coluna ou um grupo de colunas cujo valor identifica uma linha de forma única e não pode conter NULL.
Em uma tabela de clientes, customer_id distingue o registro de um cliente de todos os outros registros de clientes.
Cláusula ON
Uma cláusula ON fornece a expressão de correspondência de uma junção e pode combinar várias comparações que devem ser verdadeiras para um par.
Uma condição que associa remessas a itens de pedido usa tanto o identificador do pedido quanto o do produto para identificar o correspondente correto.
Cláusula USING
Uma cláusula USING lista colunas de mesmo nome a serem comparadas por igualdade e exibe cada coluna compartilhada listada uma vez em SELECT *.
USING (customer_id) expressa a correspondência da chave de cliente sem escrever as duas referências de coluna.
COALESCE
COALESCE retorna seu primeiro argumento que não é NULL, permitindo que um resultado exiba um valor alternativo ou uma chave disponível em qualquer uma das entradas.
COALESCE(o.total, 0) exibe zero quando o total do pedido na junção é NULL, então escolha o rótulo da coluna com cuidado.
Conciliação de contagens e totais
A conciliação compara registros que deveriam coincidir, alinhando chaves correspondentes e revelando registros ausentes ou valores diferentes.
Uma junção completa pode colocar o estoque do armazém ao lado de uma contagem física e preservar SKUs ausentes de qualquer uma das listas.
Condição de junção
Uma condição de junção é a expressão que decide se um par corresponde; apenas um resultado verdadeiro qualifica o par como correspondência.
o.customer_id = c.customer_id emparelha o pedido 101, que contém o identificador de cliente 1, com a linha de cliente cujo identificador também é 1.
COUNT(*)
COUNT(*) conta linhas de resultado, incluindo a linha de preenchimento com NULL de uma junção externa para uma linha pai sem linha filha correspondente.
Após uma junção à esquerda a partir dos clientes, um cliente sem pedido contribui com uma linha para COUNT(*).
COUNT(column)
COUNT(column) conta valores que não são NULL em uma coluna selecionada, podendo contar correspondentes opcionais reais após uma junção à esquerda.
Um cliente sem pedido tem uma chave de pedido NULL no resultado da junção, que contribui com zero para COUNT(o.order_id) no grupo desse cliente.
COUNT(DISTINCT key)
COUNT(DISTINCT key) conta cada chave diferente que não é NULL uma vez, ignorando repetições introduzidas pela correspondência com várias linhas de detalhe.
Se as três linhas de itens de um cliente contêm apenas dois identificadores de pedido, contar identificadores de pedido distintos retorna dois.

D

DISTINCT
DISTINCT remove linhas idênticas em todos os valores selecionados; ele não corrige um relacionamento incorreto nem remove duplicatas de entidades por si só.
Selecionar identificador e nome de cliente distintos mantém pessoas diferentes separadas mesmo que tenham o mesmo nome.

E

Equijunção
Uma equijunção relaciona linhas usando comparações de igualdade, frequentemente entre uma chave estrangeira e a chave primária ou única que ela referencia.
O identificador de cliente 1 em um pedido é igual ao identificador de cliente 1 na linha de cliente correspondente, então esse par satisfaz a equijunção.

F

Filtro após a junção
Um filtro após a junção é aplicado em WHERE às linhas criadas pela junção e pode remover tanto linhas correspondentes quanto linhas de junção externa preenchidas com NULL.
Uma comparação de data do lado direito em WHERE remove um cliente sem pedidos, porque a data de pedido desse cliente no resultado da junção é NULL.

G

Grade de combinações para relatório
Uma grade de combinações para relatório é uma lista completa de combinações necessárias que pode ser criada com uma junção cruzada e preenchida por uma junção à esquerda.
Combinar lojas com meses torna visíveis meses sem vendas quando as vendas reais são associadas.

H

Hierarquia
Uma hierarquia é uma estrutura de vínculos pai–filho, como relações de subordinação entre funcionários, que uma autojunção pode seguir um nível por vez.
Jamal se reporta a Hassan, que se reporta a Grace; três papéis de tabela podem mostrar essa cadeia de dois vínculos.

I

Incompatibilidade de formato das chaves
Uma incompatibilidade de formato das chaves ocorre quando identificadores vinculados usam tipos ou representações diferentes, tornando o comportamento da comparação dependente do banco de dados.
O texto “0042” e o número 42 podem corresponder por conversão no SQLite, mas precisam de tratamento consistente entre sistemas.
Item do pedido
Um item do pedido é um registro de um produto dentro de um pedido, geralmente vinculando as chaves de pedido e produto e armazenando sua quantidade.
O pedido 101 tem itens separados para Mug e Pen, então seus valores de cliente e pedido se repetem no relatório detalhado.

J

Junção
Uma junção combina linhas de entrada em linhas de resultado segundo uma regra de correspondência, podendo preservar linhas sem correspondência com valores NULL.
O nome de um cliente e o total de um pedido podem aparecer juntos após suas linhas serem juntadas pelo identificador do cliente.
Junção agrupada entre parênteses
Uma junção agrupada entre parênteses agrupa explicitamente entradas juntadas, permitindo que um grupo unido por junção interna sirva como um lado opcional de uma junção externa.
Matrículas juntadas a cursos podem formar um grupo que é depois juntado à esquerda a todos os alunos, incluindo os que não têm matrícula.
Junção cruzada
Uma junção cruzada retorna todos os pares de linhas de entrada sem uma condição de correspondência, produzindo o produto das contagens de linhas das duas entradas.
Três tamanhos de camisa combinados com duas cores produzem seis linhas possíveis de tamanho–cor para a loja.
Junção cruzada acidental
Uma junção cruzada acidental combina todos os pares de linhas porque uma condição necessária está ausente ou é sempre verdadeira, produzindo correspondências sem relação.
Uma condição esquecida faz um cliente aparecer ao lado dos pedidos de outros clientes, além dos próprios pedidos, aumentando o resultado.
Junção externa à direita
Uma junção externa à direita preserva todas as linhas à direita, adicionando valores NULL à esquerda quando uma linha à direita não tem correspondente que atenda à condição.
Com orders à direita, um pedido sem cadastro 104 com referência de cliente NULL permanece, embora nenhuma linha de cliente possa corresponder a ele.
Junção externa à esquerda
Uma junção externa à esquerda preserva cada linha à esquerda, retornando cada par correspondente ou uma linha com colunas à direita preenchidas com NULL quando não há correspondente.
Um cliente que nunca fez um pedido ainda aparece em um relatório de clientes com junção à esquerda, com colunas de pedido NULL.
Junção externa completa
Uma junção externa completa retorna pares correspondentes e preserva linhas sem correspondência das duas entradas com valores NULL para cada correspondente ausente.
Uma junção completa cliente–pedido preserva clientes sem pedidos e pedidos sem cadastro ao lado dos pedidos correspondentes.
Junção interna
Uma junção interna retorna todos os pares que satisfazem sua condição de junção e exclui linhas de qualquer uma das entradas que não encontram correspondência.
Se Ana tem dois pedidos e Ben tem um, uma junção interna de clientes e pedidos retorna esses três pedidos e deixa de fora uma compra sem cadastro.
Junção natural
Uma junção natural compara automaticamente todos os nomes de coluna compartilhados pelas entradas, então alterações nos nomes compartilhados podem mudar seu resultado.
Adicionar uma coluna de cidade de entrega a orders faz uma junção natural comparar cidades além de identificadores de cliente.
Junção por desigualdade
Uma junção por desigualdade relaciona linhas usando uma comparação diferente da igualdade, como um preço entre os limites inferior e superior de uma faixa.
Uma caneca com preço de 8,00 fica na faixa de preço chamada Standard e é juntada ao rótulo dessa faixa.
Junção por vírgulas
Uma junção por vírgulas nomeia tabelas separadas por vírgulas em FROM e expressa sua condição de correspondência na cláusula WHERE da consulta.
Remover o teste da chave de cliente de uma junção por vírgulas de quatro clientes e quatro pedidos faz cada cliente formar par com cada pedido.

L

Lado opcional
O lado opcional de uma junção à esquerda é a entrada à direita, cujas colunas são preenchidas com NULL quando uma linha preservada não tem correspondência.
Pedidos são opcionais em um relatório de todos os clientes, então um pedido ausente não deve remover o cliente.
Lado preservado
O lado preservado de uma junção externa é a entrada cujas linhas sem correspondência devem ser retornadas antes da ação de junções ou filtros posteriores.
Clientes são o lado preservado em customers c LEFT JOIN orders o, independentemente do número de pedidos.
Linha com colunas preenchidas com NULL
Uma linha com colunas preenchidas com NULL é um resultado de junção externa que preserva uma linha de entrada sem correspondência e fornece NULL para as colunas do correspondente ausente.
O número de pedido NULL de um cliente no resultado de uma junção à esquerda indica um pedido correspondente ausente; não é um pedido armazenado.

M

Matrícula
Uma matrícula vincula um aluno a um curso e pode ser representada por uma linha de tabela associativa com essas duas chaves de identificação.
Os cursos Algebra e Biology de Mia exigem linhas de matrícula separadas; Omar não tem linha de matrícula.
Multiplicação de linhas
A multiplicação de linhas repete uma linha pai para cada linha filha correspondente, o que é útil para listas de detalhes, mas pode multiplicar totais do nível da linha pai.
Se o pedido 101, com total de 22,00, tem dois itens, ele aparece duas vezes após a junção com seus itens, então esse total seria somado duas vezes.

N

Nível de agregação
Um nível de agregação é o tipo de registro que uma contagem ou soma pretende medir, como clientes, pedidos ou itens de pedido.
Conte identificadores distintos de pedido quando as linhas da junção representam itens, mas o relatório pergunta quantos pedidos existem.
Nome de coluna qualificado
Um nome de coluna qualificado inclui um nome ou apelido de tabela antes da coluna, identificando qual entrada fornece o valor.
c.customer_id seleciona a chave do lado dos clientes quando as duas tabelas da junção contêm customer_id.

P

Par de uma linha com ela mesma
Um par de uma linha com ela mesma relaciona uma linha a si mesma quando uma condição de autojunção permite que os dois apelidos se refiram à mesma chave de identificação.
Uma linha de funcionário forma par com ela mesma quando a condição de uma autojunção verifica apenas se os identificadores de gerente dos dois aliases são iguais.
Par não ordenado
Um par não ordenado trata dois membros como o mesmo par em qualquer ordem; comparar identificadores distintos com < mantém o par uma vez.
O par de colegas Hassan–Iris aparece uma vez quando a condição exige que o primeiro identificador de funcionário seja menor.
Previsão da quantidade de linhas
Uma previsão da quantidade de linhas estima o resultado de uma junção a partir dos relacionamentos de correspondência e das linhas sem correspondência que seu tipo de junção preserva.
Três pedidos correspondentes mais dois clientes sem correspondência preveem cinco linhas para a junção à esquerda a partir dos clientes.
Produto cartesiano
Um produto cartesiano é o conjunto completo de combinações formadas pela escolha de uma linha de cada tabela de entrada.
Colocar cada cliente ao lado de cada pedido forma todos os pares possíveis de cliente–pedido, incluindo pares sem relação.

R

Referência ambígua a coluna
Uma referência ambígua a coluna é uma referência não qualificada que pode nomear uma coluna em mais de uma entrada, deixando sua origem indefinida.
Com JOIN ... ON, selecionar customer_id sem qualificação falha quando customers e orders fornecem essa coluna.
Relacionamento muitos para muitos
Um relacionamento muitos para muitos permite que linhas de qualquer um dos lados tenham vários correspondentes e é representado por uma tabela de pares de vínculos.
Quando um aluno faz dois cursos e um curso inclui dois alunos, uma tabela enrollments registra cada par aluno–curso.
Relacionamento um para muitos
Um relacionamento um para muitos permite que uma linha pai tenha várias linhas filhas, com a chave estrangeira armazenada no lado filho.
Quando um cliente tem dois pedidos, as duas linhas de pedido se referem ao identificador desse cliente sem repetir o endereço.
Relacionamento um para um
Um relacionamento um para um permite no máximo um correspondente por linha em qualquer um dos lados, geralmente por meio de uma chave estrangeira que também é única.
Se cada funcionário pode ter no máximo um crachá, uma referência única ao funcionário na tabela de crachás impõe esse vínculo.
Restrição de correspondência
Uma restrição de correspondência limita quais correspondentes candidatos são elegíveis em ON, enquanto uma junção externa ainda preserva as linhas necessárias de suas entradas.
Uma data limite de pedido em ON preserva todos os clientes, mas associa apenas pedidos que atendem a esse limite.
Resultado desconhecido de comparação
Um resultado desconhecido de comparação ocorre na igualdade comum com NULL e não conta como verdadeiro para correspondência ou filtragem em WHERE.
O pedido sem cadastro 104 tem uma referência de cliente NULL, então não pode corresponder nem a outro NULL por igualdade.

T

Tabela associativa
Uma tabela associativa registra uma linha por par de relacionamento e contém uma chave estrangeira para cada extremidade de um vínculo muitos para muitos.
Cada linha de matrícula vincula um aluno a um curso, permitindo que tanto alunos quanto cursos se repitam.
Teste IS NULL
Um teste IS NULL é verdadeiro quando um valor é NULL e pode selecionar correspondentes ausentes após uma junção externa se for aplicado a uma chave adequada.
Testar o.order_id IS NULL mantém clientes sem pedidos; testar o.order_id = NULL não mantém nenhuma linha.

V

Vínculo dependente
Um vínculo dependente conecta uma tabela posterior por meio de uma coluna de uma tabela juntada anteriormente, então correspondentes anteriores ausentes o afetam.
Uma junção com cursos depende do identificador de curso da matrícula; um aluno sem matrícula tem um identificador de curso NULL que não pode satisfazer essa igualdade.

Sobre esta aula

Por StudeliRelatar um erro

Crie seus próprios Materiais de Estudo

Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.

Começar