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

Localizar registros em que a junção não existe


Use um EXISTS expressão:
WHERE NOT EXISTS (
   SELECT FROM votes v  -- SELECT list can be empty
   WHERE  v.some_id = base_table.some_id
   AND    v.user_id = ?
   )

A diferença


... entre NOT EXISTS() (Ⓔ) e NOT IN() (Ⓘ) é duplo:

  1. Desempenho

    Ⓔ é geralmente mais rápido. Ele para de processar a subconsulta assim que a primeira correspondência for encontrada. O manual:

    A subconsulta geralmente só será executada por tempo suficiente para determinar se pelo menos uma linha é retornada, não até a conclusão.

    Ⓘ também pode ser otimizado pelo planejador de consultas, mas em menor grau, pois NULL manuseio torna-o mais complexo.

  2. Correção

    Se um dos valores resultantes na expressão de subconsulta for NULL , o resultado de Ⓘ é NULL , enquanto a lógica comum esperaria TRUE - e Ⓔ retornará TRUE . O manual:

    Se todos os resultados por linha forem desiguais ou nulos, com pelo menos um nulo, o resultado de NOT IN é nulo.

Essencialmente, (NOT) EXISTS é a melhor escolha na maioria dos casos.

Exemplo


Sua consulta pode ficar assim:
SELECT *
FROM   questions q
WHERE  NOT EXISTS (
    SELECT FROM votes v 
    WHERE  v.question_id = q.id
    AND    v.user_id = ?
    );

não junte-se a votes na consulta básica. Isso anularia o esforço.

Além de NOT EXISTS e NOT IN existem opções de sintaxe adicionais com LEFT JOIN / IS NULL e EXCEPT . Ver:
  • Selecione as linhas que não estão presentes em outra tabela