PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Selecione linhas que não estão presentes em outra tabela


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 que EXCEPT 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