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é
NULLla 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