PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Trova i record in cui il join non esiste

Usa un EXISTS espressione:

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 differenza

... tra NOT EXISTS() (Ⓔ) e NOT IN() (Ⓘ) è duplice:

  1. Prestazioni

    Ⓔ è generalmente più veloce. Interrompe l'elaborazione della sottoquery non appena viene trovata la prima corrispondenza. Il manuale:

    La sottoquery verrà generalmente eseguita solo per un tempo sufficiente a determinare se viene restituita almeno una riga, non fino al completamento.

    Ⓘ può anche essere ottimizzato dal pianificatore di query, ma in misura minore poiché NULL la gestione lo rende più complesso.

  2. Correttezza

    Se uno dei valori risultanti nell'espressione della sottoquery è NULL , il risultato di Ⓘ è NULL , mentre la logica comune si aspetterebbe TRUE - e Ⓔ restituirà TRUE . Il manuale:

    Se tutti i risultati per riga sono diversi o nulli, con almeno uno null, il risultato di NOT IN è nullo.

In sostanza, (NOT) EXISTS è la scelta migliore nella maggior parte dei casi.

Esempio

La tua richiesta può assomigliare a questa:

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

non partecipa a votes nella query di base. Ciò annullerebbe lo sforzo.

Oltre a NOT EXISTS e NOT IN ci sono ulteriori opzioni di sintassi con LEFT JOIN / IS NULL e EXCEPT . Vedi:

  • Seleziona le righe che non sono presenti in un'altra tabella