Existem basicamente 4 técnicas para esta tarefa, todas elas SQL padrão.
NOT EXISTS
Muitas vezes mais rápido no Postgres.
SELECT ip
FROM login_log l
WHERE NOT EXISTS (
SELECT -- SELECT list mostly irrelevant; can just be empty in Postgres
FROM ip_location
WHERE ip = l.ip
);
Considere também:
- O que é mais fácil de ler nas subconsultas EXISTS?
LEFT JOIN / IS NULL
Às vezes isso é mais rápido. Muitas vezes o mais curto. Geralmente resulta no mesmo plano de consulta que
NOT EXISTS
. SELECT l.ip
FROM login_log l
LEFT JOIN ip_location i USING (ip) -- short for: ON i.ip = l.ip
WHERE i.ip IS NULL;
EXCEPT
Baixo. Não é tão facilmente integrado em consultas mais complexas.
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
Observe que (por documentação):
duplicatas são eliminadas a menos queEXCEPT ALL
é usado.
Normalmente, você deseja que o
ALL
palavra-chave. Se você não se importa, ainda use porque torna a consulta mais rápida . NOT IN
Apenas bom sem
NULL
valores ou se você sabe lidar com NULL
devidamente. Eu não usá-lo para este fim. Além disso, o desempenho pode se deteriorar com mesas maiores. SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
carrega uma "armadilha" para NULL
valores de cada lado:- Encontrar registros em que a junção não existe
Pergunta semelhante no dba.SE direcionado ao MySQL:
- Selecione as linhas em que o valor da segunda coluna não está presente na primeira coluna