SELECIONE * ONDE NÃO EXISTE

94

Acho que estou indo pelo caminho certo com este ... Tenha paciência, pois meu SQL não é o melhor

Estou tentando consultar um banco de dados para selecionar tudo de uma tabela onde certas células não existem em outra. Isso não faz muito sentido, mas espero que este código

SELECT * from employees WHERE NOT EXISTS (SELECT name FROM eotm_dyn)

Basicamente, tenho uma tabela com uma lista de funcionários e seus detalhes. Em seguida, outra tabela com alguns outros detalhes, incluindo seu nome. Onde o nome não está na tabela eotm_dyn, o que significa que não há entrada para eles, gostaria de ver exatamente quem são, ou em outras palavras, ver o que exatamente está faltando.

A consulta acima não retorna nada, mas sei que faltam nomes 20, então obviamente não acertei.

Alguém pode ajudar?

Ciaran
fonte

Respostas:

160

Você não se juntou à mesa em sua consulta.

Sua consulta original sempre retornará nada, a menos que não haja nenhum registro eotm_dyn; nesse caso, ela retornará tudo.

Supondo que essas tabelas devam ser unidas employeeID, use o seguinte:

SELECT  *
FROM    employees e
WHERE   NOT EXISTS
        (
        SELECT  null 
        FROM    eotm_dyn d
        WHERE   d.employeeID = e.id
        )

Você pode juntar essas tabelas com uma LEFT JOINpalavra - chave e filtrar os NULL, mas provavelmente será menos eficiente do que usar NOT EXISTS.

Quassnoi
fonte
30
Preciso de "ONDE NÃO EXISTE" duas vezes por ano e sempre esqueço como usá-lo exatamente. Obrigado - este exemplo será marcado agora.
Mateng,
1
Alguém poderia fornecer uma referência para "O filtro LEFT JOIN + NULL é menos eficiente do que NOT EXISTS"? Pode ser óbvio, mas nunca vi isso nos documentos. Obrigado.
toni07
2
@ toni07 Na verdade, isso é uma lenda. LEFT JOIN ganha. explainextended.com/2009/09/18/… .. O blog de Quassnoi é sempre um recurso útil.
Kaii
como eu usaria isso em uma cláusula HAVING? akagroup by X having exist [row with employeeID = e.id]
phil294
@blauhirn: assim mesmo
Quassnoi
83
SELECT * FROM employees WHERE name NOT IN (SELECT name FROM eotm_dyn)

OU

SELECT * FROM employees WHERE NOT EXISTS (SELECT * FROM eotm_dyn WHERE eotm_dyn.name = employees.name)

OU

SELECT * FROM employees LEFT OUTER JOIN eotm_dyn ON eotm_dyn.name = employees.name WHERE eotm_dyn IS NULL
Robin Day
fonte
1
NB! NOT INnão funciona como esperado se nametiver nullvalores. Assista a 36min 20seg no vídeo SESSÃO: 10 técnicas de ajuste de consulta que todo programador de SQL deve saber (Kevin Kline, Aaron Bertrand) .
hlovdal
12

Você pode fazer um LEFT JOIN e afirmar que a coluna associada é NULL.

Exemplo:

SELECT * FROM employees a LEFT JOIN eotm_dyn b on (a.joinfield=b.joinfield) WHERE b.name IS NULL
Mike Tunnicliffe
fonte
7
SELECT * from employees
WHERE NOT EXISTS (SELECT name FROM eotm_dyn)

Nunca retorna nenhum registro, a menos que eotm_dynesteja vazio. Você precisa de algum tipo de critério SELECT name FROM eotm_dyncomo

SELECT * from employees
WHERE NOT EXISTS (
    SELECT name FROM eotm_dyn WHERE eotm_dyn.employeeid = employees.employeeid
)

assumindo que as duas tabelas estão vinculadas por um relacionamento de chave estrangeira. Neste ponto, você pode usar uma variedade de outras opções, incluindo LEFT JOIN. O otimizador normalmente os tratará da mesma forma na maioria dos casos.

Cade Roux
fonte
4

Você também pode dar uma olhada nesta questão relacionada . Esse usuário relatou que o uso de uma junção proporcionou um desempenho melhor do que o uso de uma subconsulta.

Andre Miller
fonte