Como excluir linhas que não se juntam a outra tabela?

86

Eu tenho duas tabelas, uma tem uma chave primária e outra como uma chave estrangeira.

Quero extrair dados da tabela primária, apenas se a tabela secundária não tiver uma entrada contendo sua chave. Uma espécie de oposto de uma junção interna simples, que retorna apenas as linhas que se unem por essa chave.

Chaddeus
fonte

Respostas:

269

texto alternativo

SELECT <select_list> 
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL

Imagem completa de junção texto alternativo

De um artigo: http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx

Pranay Rana
fonte
9
finalmente! por que eles não têm em livros didáticos e por que meus professores na uni não tinham ?! eles usaram as piores explicações possíveis do mundo, nem remotamente perto dessas!
pythonian29033
4
Isso é ouro. Eu odeio escrever um comentário que não tem conteúdo, apenas elogios efusivos, mas vamos lá! Esta é uma resposta incrível. Obrigada, @Pranay Rana.
0xbe5077ed
1
Por favor, explique para mim, por que, B.Key IS NULLmas ainda somos comparáveis A.Key = B.Key?
Faça Nhu Vy
1
@DoNhuVy simples, a comparação está na cláusula "ON", em uma junção LEFT ou RIGHT se não houver nenhuma linha correspondente, então uma linha com todos os NULLs é juntada, após o qual você testa IS NULL para saber que não há nenhuma linha correspondente . (A propósito, isso só funciona se o campo que você está testando não for NULL, ou seja, não pode ter NULL por algum outro motivo)
Gregory Magarshak
Estou usando a consulta abaixo: SELECT A. * FROM #PurgeFilesListNew A FULL OUTER JOIN #DoNotPurgeFilesListNew B ON A.JobFileId = B.JobFileId AND A.AccountID = B.AccountID ONDE A.JobFileId É NULO OU B.JobFileId É NULO E A.AccountID IS NULL OU B.AccountID IS NULL Basicamente, estou tendo dois comparando dois valores na cláusula "ON". Está funcionando bem, mas a consulta está retornando uma linha nula para as linhas que não correspondem. Como resolver isso? Por favor, ajude
HarshSharma
10
SELECT
   *
FROM
   primarytable P
WHERE
   NOT EXISTS (SELECT * FROM secondarytable S
     WHERE
         P.PKCol = S.FKCol)

Geralmente , (NOT) EXISTSé uma escolha melhor (NOT) INou(LEFT) JOIN

gbn
fonte
bem, ele não postou qual DBRMS é usado, no entanto, no MySql LEFT JOINsuperaNOT EXIST
The Scrum Meister
@The Scrum Meister: eu disse mais rápido? Pesquise IN vs EXISTS vs JOIN para descobrir as diferenças semânticas e lógicas ...
gbn
@gbn Desculpe, pensei que por "melhor escolha" você quis dizer mais rápido. Você pode explicar de que forma é a melhor escolha? explainextended.com/2009/09/18/…
The Scrum Meister
1
@The Scrum Meister: geralmente, qualquer tipo de JOIN pode precisar de um DISTINCT. NOT IN com um nulo na lista resulta em falso. IN / EXISTS se comportam da mesma forma. No entanto, a única construção "segura" é (NÃO) EXISTE, a menos que você goste de inconsistência
gbn
4

use uma junção à esquerda "não existe":

SELECT p.*
FROM primary_table p LEFT JOIN second s ON p.ID = s.ID
WHERE s.ID IS NULL
O Scrum Meister
fonte
4

Outra solução é:

SELECT * FROM TABLE1 WHERE id NOT IN (SELECT id FROM TABLE2)
Ali Akbar
fonte
3
SELECT P.*
FROM primary_table P
LEFT JOIN secondary_table S on P.id = S.p_id
WHERE S.p_id IS NULL
Tommi
fonte
2
Tenho uma pergunta ... se estivermos usando a condição P.key = S.keye dissermos where S.key IS NULL, isso também não torna P.key nulo?
Somjit
2

Se você quiser selecionar as colunas da Primeira Tabela "que também estão presentes na Segunda Tabela, neste caso você também pode usar EXCEPT. Neste caso, os nomes das colunas também podem ser diferentes, mas o tipo de dados deve ser o mesmo.

Exemplo:

select ID, FName
from FirstTable
EXCEPT
select ID, SName
from SecondTable
Anil Soman
fonte
0

Isso foi útil para usar no COGNOS porque a criação de uma instrução SQL "Not in" no Cognos era permitida, mas demorava muito para ser executada. Eu havia codificado manualmente a tabela A para unir à tabela B no Cognos como A.key "não em" B.key, mas a consulta estava demorando muito / não retornava resultados após 5 minutos.

Para qualquer pessoa que esteja procurando uma solução "NOT IN" no Cognos, aqui está o que eu fiz. Crie uma consulta que une as tabelas A e B com um LEFT JOIN no Cognos selecionando o tipo de link: a tabela A.Key tem valores "0 a N" na tabela B e, em seguida, adicionou um Filtro (correspondem às cláusulas Where) para: tabela B .Key é NULL.

Correu rápido e como um encanto.

JennyB
fonte