PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Rechercher des enregistrements où la jointure n'existe pas

Utiliser un EXISTS expression :

WHERE NOT EXISTS (
   SELECT FROM votes v  -- SELECT list can be empty
   WHERE  v.some_id = base_table.some_id
   AND    v.user_id = ?
   )

La différence

... entre NOT EXISTS() (Ⓔ) et NOT IN() (Ⓘ) est double :

  1. Performances

    Ⓔ est généralement plus rapide. Il arrête de traiter la sous-requête dès que la première correspondance est trouvée. Le manuel :

    La sous-requête ne sera généralement exécutée qu'assez longtemps pour déterminer si au moins une ligne est renvoyée, pas jusqu'à la fin.

    Ⓘ peut également être optimisé par le planificateur de requêtes, mais dans une moindre mesure puisque NULL la manipulation le rend plus complexe.

  2. Correctivité

    Si l'une des valeurs résultantes dans l'expression de sous-requête est NULL , le résultat de Ⓘ est NULL , alors que la logique commune attendrait TRUE - et Ⓔ renverra TRUE . Le manuel :

    Si tous les résultats par ligne sont inégaux ou nuls, avec au moins un nul, alors le résultat de NOT IN est nul.

Essentiellement, (NOT) EXISTS est le meilleur choix dans la plupart des cas.

Exemple

Votre requête peut ressembler à ceci :

SELECT *
FROM   questions q
WHERE  NOT EXISTS (
    SELECT FROM votes v 
    WHERE  v.question_id = q.id
    AND    v.user_id = ?
    );

Ne pas participer aux votes dans la requête de base. Cela annulerait l'effort.

Outre NOT EXISTS et NOT IN il existe des options de syntaxe supplémentaires avec LEFT JOIN / IS NULL et EXCEPT . Voir :

  • Sélectionner les lignes qui ne sont pas présentes dans un autre tableau