Junções SQL e relacionamentos entre tabelas
BásicoAula 5 de 6 do curso Curso de Noções básicas de SQL
O que você vai aprender
- 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 esquemaUse 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 linhasDescreva 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.
- Identificar os vínculos entre tabelas em um esquema
- 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 ONJunte 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 intervaloReconheç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.
- Escrever uma junção interna com ON
- 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 JOINEscreva 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 JOINPreserve 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 WHEREExplique 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.
- Preservar todas as linhas de uma tabela com LEFT JOIN
- 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çãoJunte 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 cruzadaUse 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.
- Relacionar linhas da mesma tabela com uma autojunção
- 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 associativaExplique 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 consultaPlaneje 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çõesCombine junções externas e internas em uma cadeia sem perder as linhas que você pretendia preservar e verifique cada etapa da cadeia.
- Consultar relacionamentos muitos para muitos por meio de uma tabela associativa
- 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 infladosExplique 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 nelePreveja 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.
- Corrigir linhas duplicadas e totais inflados
Guia de estudo de Junções SQL
1Chaves 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_id | name | city |
|---|---|---|
| 1 | Ana | Denver |
| 2 | Ben | Austin |
| 3 | Chloe | Denver |
| 4 | Dev | Boston |
| order_id | customer_id | order_date | total |
|---|---|---|---|
| 101 | 1 | 2026-03-02 | 22,00 |
| 102 | 1 | 2026-03-15 | 25,50 |
| 103 | 2 | 2026-03-20 | 60,00 |
| 104 | NULL | 2026-03-21 | 15,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
| Relacionamento | Significado | Onde fica o vínculo |
|---|---|---|
| Um para um | Cada 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 muitos | Uma 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 muitos | As 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
WHEREfiltrá-las eSELECTescolher as colunas. - Use
ORDER BYquando a ordem das linhas for importante.
2Como 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 é:
| name | order_id | total |
|---|---|---|
| Ana | 101 | 22,00 |
| Ana | 102 | 25,50 |
| Ben | 103 | 60,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
JOINsignificaINNER JOIN: linhas sem correspondência de qualquer um dos lados são excluídas.- Coloque o relacionamento em
ONe 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
USINGcompara as colunas listadas de mesmo nome e mostra cada chave compartilhada uma vez.NATURAL JOINdepende 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 sintaxeUSINGouNATURAL JOIN.
3Preservar 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;
| name | order_id | total |
|---|---|---|
| Ana | 101 | 22,00 |
| Ana | 102 | 25,50 |
| Ben | 103 | 60,00 |
| Chloe | NULL | NULL |
| Dev | NULL | NULL |
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 NULLem 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.
COALESCEpode 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ção | Linhas sem correspondência preservadas |
|---|---|
| LEFT JOIN | Apenas da entrada à esquerda |
| RIGHT JOIN | Apenas da entrada à direita |
| FULL OUTER JOIN | Das 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 fazer | Posição típica em uma junção à esquerda |
|---|---|
| Limitar as correspondências elegíveis à direita enquanto preserva todas as linhas à esquerda | ON |
| Limitar quais linhas à esquerda pertencem ao relatório | WHERE |
| Encontrar linhas cujo correspondente à direita está ausente | WHERE 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
ONdecide as correspondências;WHEREfiltra as linhas de resultado concluídas.- Coloque uma restrição do lado direito em
ONpara 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
WHEREremove linhas preenchidas com NULL quando é desconhecida. - O teste
IS NULLda antijunção é executado intencionalmente após a junção.
4Autojunçõ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_id | name | manager_id |
|---|---|---|
| 1 | Grace | NULL |
| 2 | Hassan | 1 |
| 3 | Iris | 1 |
| 4 | Jamal | 2 |
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_idde um funcionário aoemp_iddo 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.
DISTINCTnão remove pares incorretos.
5Tabelas 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_id | course_id |
|---|---|
| 1 | 10 |
| 1 | 20 |
| 2 | 10 |
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_id | name | price |
|---|---|---|
| 1 | Mug | 8,00 |
| 2 | Pen | 1,50 |
| 3 | Notebook | 4,25 |
| 4 | Stapler | 12,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 é:
| name | order_id | product | quantity | line_total |
|---|---|---|---|---|
| Ana | 101 | Mug | 2 | 16,00 |
| Ana | 101 | Pen | 4 | 6,00 |
| Ana | 102 | Notebook | 6 | 25,50 |
| Ben | 103 | Mug | 6 | 48,00 |
| Ben | 103 | Pen | 8 | 12,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
ONpode 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
WHEREainda pode remover linhas preservadas por junções à esquerda. - Examine a contagem e as chaves que permanecem após cada etapa.
6Contagens 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
| Sinal | O que examinar |
|---|---|
| Cada linha à esquerda forma um par com cada linha à direita | Condição ausente ou condição sempre verdadeira |
| Nenhuma correspondência ou entidades sem relação emparelhadas | Colunas erradas ou valores de chave incompatíveis |
| Um registro lógico tem vários correspondentes | Chave incompleta, chave de consulta duplicada ou vínculo um para muitos esperado |
| Linhas pai sem linhas filhas desaparecem | Junçã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
1Dos vínculos no esquema às linhas juntadas
10 passos
- 1Introduçã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.
- 2ExemploLeia 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. - 3Explicaçã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.
- 4DesafioEncontre 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.
- 5ExemploForme 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.
- 6Ideia-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.
- 7DicaIndique de onde vem uma coluna
Dê apelidos às referências de tabela, como
customers ceorders o. Escrevac.namepara o nome do cliente eo.totalpara o total do pedido.As duas entradas têm
customer_id. ComJOIN ... ON, selecionar apenas esse nome é ambíguo; qualifique-o comoc.customer_idouo.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. - 8ExplicaçãoA correspondência vem antes da filtragem
Leia a ordem lógica como junções, depois
WHERE, depoisSELECTe depoisORDER 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. - 9DesafioPreveja 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.
- 10Recapitulaçã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.
2Criar e interpretar junções internas
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoExija um correspondente dos dois lados
- 2ExemploEscreva a condição de chave
- 3ExemploLeia as três linhas de saída
- 4DesafioAdicione um filtro de clientes
- 5DicaCompare a identidade completa
- 6ExplicaçãoUse uma abreviação para nomes compartilhados
- 7DesafioObserve o que NATURAL altera
- 8ConexãoLeia uma junção antiga por vírgulas
- 9ExemploRelacione preços a faixas
- 10DesafioPreveja uma sobreposição e uma lacuna
- 11RecapitulaçãoLeia a condição por trás da sintaxe
3Preservar linhas sem correspondência sem perdê-las em filtros
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoDecida quais registros devem permanecer
- 2ExemploPreserve todos os clientes
- 3DesafioMude o lado que deve ser preservado
- 4DicaTeste a chave do correspondente ausente
- 5ExplicaçãoLeia uma junção à direita como uma junção à esquerda invertida
- 6ExemploPreserve registros sem correspondência dos dois lados
- 7DesafioConcilie duas novas listas de chaves
- 8DicaVerifique o suporte a junções externas
- 9ExemploRestrinja os pedidos correspondentes em ON
- 10ExemploMova o teste de data para WHERE
- 11DesafioFiltre a tabela à esquerda intencionalmente
- 12ConexãoDecida o que significa um zero exibido
- 13DesafioPreserve todos com atividade recente
- 14RecapitulaçãoMantenha correspondência e filtragem separadas
4Acompanhar gerentes e criar combinações
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoEscolha papéis ou possibilidades
- 2ExemploLeia as relações de subordinação
- 3DesafioPreserve a pessoa no topo
- 4ConexãoSuba mais um nível
- 5ExemploForme pares de colegas uma vez
- 6ExemploCrie seis possibilidades de camisa
- 7DesafioPreveja o efeito de outra entrada
- 8Ideia-chaveCrie uma grade completa para relatório
- 9DicaCorrija a condição ausente
- 10DesafioRelacione regras de pares ao tamanho do produto
- 11RecapitulaçãoDê a cada formação de pares um propósito claro
5Seguir uma tabela associativa e preservar um caminho mais longo
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoPlaneje o caminho até os dados
- 2ExemploLeia os vínculos de matrícula
- 3ExemploAtravesse a tabela associativa em duas etapas
- 4DesafioEncontre um curso sem alunos
- 5ExplicaçãoEstenda o caminho da loja
- 6ExemploExpanda o pedido 101 em itens
- 7ExemploLeia as demais linhas de compra
- 8DesafioEscolha o vínculo com produtos
- 9ExemploVeja uma junção posterior remover clientes
- 10ExemploLeve a linha ausente adiante
- 11DesafioPreserve o aluno sem matrícula
- 12ConexãoCrie um grupo opcional explicitamente
- 13DesafioVerifique o filtro do relatório concluído
- 14RecapitulaçãoExamine o caminho inteiro
6Corrigir totais inflados e verificar o resultado
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoNomeie o que está sendo medido
- 2ExemploObserve a repetição de um total de pedido
- 3DicaSome um dado em seu próprio nível
- 4DesafioDescarte uma correção baseada no valor
- 5ExemploConte uma identidade ou uma linha de preenchimento
- 6Ideia-chaveDuas listas filhas se multiplicam
- 7ExplicaçãoPreveja a dimensão antes de executar
- 8DesafioLocalize uma chave incompleta
- 9DicaVerifique a tabela de consulta e o formato da chave
- 10ExemploNão relacione chaves ausentes por igualdade
- 11DesafioEscolha uma medida correta para o relatório
- 12RecapitulaçãoVerifique o significado e também as contagens
Questões de Junções SQL
Conjunto 1: Interpretar relacionamentos e escolher linhas correspondentes10 Questões de Prática
Questão 1 de 10
Mostrar respostaOcultar resposta
Questão 2 de 10
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?Mostrar respostaOcultar resposta
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?Mostrar respostaOcultar resposta
Questão 4 de 10
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?Mostrar respostaOcultar resposta
Questão 5 de 10
(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?Mostrar respostaOcultar resposta
Questão 6 de 10
Mostrar respostaOcultar resposta
Questão 7 de 10
(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?Mostrar respostaOcultar resposta
Questão 8 de 10
Mostrar respostaOcultar resposta
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?Mostrar respostaOcultar resposta
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?Mostrar respostaOcultar resposta
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
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
note pode ser NULL. Após desks LEFT JOIN reservations, qual teste WHERE encontra apenas mesas sem reserva?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
departments d LEFT JOIN employees e ON e.department_id = d.department_id. Onde deve ficar e.active = 1?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
SUM(total) e SUM(DISTINCT total)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
code. Alguns clientes resultantes da junção aparecem duas vezes. Qual consulta de diagnóstico encontra códigos de consulta repetidos?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
ON combina uma tabela de 4 colunas com uma tabela de 3 colunas. Qual é a largura de SELECT * antes de remover qualquer coluna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
<>. Quantas linhas são retornadas e quantas < retornaria?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
from_code e to_code, ambos se referindo a airports.code. Como um relatório deve obter os dois nomes de aeroportos?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
COUNT(t.task_id) retorna se identificadores de tarefa não podem ser NULL?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
COUNT(article_id) e COUNT(DISTINCT award_id)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
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?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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
AND r.name = 'East' em ON. Quais linhas aparecem ao selecionar região e escritório?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
(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?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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
WHERE service.category = 'Repair'. O serviço de A é Repair. O que permanece?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
SELECT DISTINCT name e SELECT DISTINCT subscriber_id, name retornam?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
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
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
[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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
WHERE a.k IS NULL OR b.k IS NULL?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
WHERE o.date >= '2026-09-01' OR o.order_id IS NULL. Quais clientes permanecem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
(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?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
groups LEFT JOIN signups JOIN classes com groups LEFT JOIN (signups JOIN classes), usando as chaves relevantes. O que acontece com H?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
COUNT(*), COUNT(DISTINCT bill_id) e COUNT(DISTINCT case_id)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
AND em uma condição de junção
Antijunção
Apelido de tabela
FROM customers c, o apelido c permite que a consulta se refira ao nome do cliente como c.name.Atributo do relacionamento
Autojunção
manager_id, e o apelido de gerente fornece o emp_id correspondente.C
Cadeia de junções
Cadeia de junções internas e externas
Caminho de junção
Chave composta
Chave de consulta duplicada
Chave estrangeira
Chave primária
customer_id distingue o registro de um cliente de todos os outros registros de clientes.Cláusula ON
Cláusula USING
SELECT *.USING (customer_id) expressa a correspondência da chave de cliente sem escrever as duas referências de coluna.COALESCE
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
Condição de junção
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(*).COUNT(column)
COUNT(o.order_id) no grupo desse cliente.COUNT(DISTINCT key)
D
DISTINCT
E
Equijunção
F
Filtro após a junção
WHERE às linhas criadas pela junção e pode remover tanto linhas correspondentes quanto linhas de junção externa preenchidas com NULL.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
H
Hierarquia
I
Incompatibilidade de formato das chaves
Item do pedido
J
Junção
Junção agrupada entre parênteses
Junção cruzada
Junção cruzada acidental
Junção externa à direita
Junção externa à esquerda
Junção externa completa
Junção interna
Junção natural
Junção por desigualdade
Junção por vírgulas
FROM e expressa sua condição de correspondência na cláusula WHERE da consulta.L
Lado opcional
Lado preservado
customers c LEFT JOIN orders o, independentemente do número de pedidos.Linha com colunas preenchidas com NULL
M
Matrícula
Multiplicação de linhas
N
Nível de agregação
Nome de coluna qualificado
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
Par não ordenado
< mantém o par uma vez.Previsão da quantidade de linhas
Produto cartesiano
R
Referência ambígua a coluna
JOIN ... ON, selecionar customer_id sem qualificação falha quando customers e orders fornecem essa coluna.Relacionamento muitos para muitos
Relacionamento um para muitos
Relacionamento um para um
Restrição de correspondência
ON, enquanto uma junção externa ainda preserva as linhas necessárias de suas entradas.ON preserva todos os clientes, mas associa apenas pedidos que atendem a esse limite.Resultado desconhecido de comparação
T
Tabela associativa
Teste IS NULL
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
Sobre esta aula
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.