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:
-
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. -
Correttezza
Se uno dei valori risultanti nell'espressione della sottoquery è
NULL
, il risultato di Ⓘ èNULL
, mentre la logica comune si aspetterebbeTRUE
- 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