Perché NOT IN con un set contenente NULL restituisce sempre FALSE / NULL?


21

Ho avuto una query (per Postgres e Informix) con una NOT INclausola contenente una sottoquery che in alcuni casi restituiva NULLvalori, facendo sì che quella clausola (e l'intera query) non restituissero nulla.

Qual è il modo migliore per capirlo? Ho pensato NULLa qualcosa senza valore e quindi non mi aspettavo che la query fallisse, ma ovviamente non è questo il modo corretto di pensare NULL.

Risposte:


29

Logica booleana - o logica a tre valori

  • IN è una scorciatoia per una serie di condizioni OR
  • x NOT IN (1, 2, NULL) equivale a NOT (x = 1 OR x = 2 OR x = NULL)
  • ... equivale a x <> 1 AND x <> 2 AND x <> NULL
  • ... è uguale a true AND true AND unknown**
  • ... = unknown**
  • ... che è quasi lo stesso falsedi questo caso in quanto non passerà la WHEREcondizione **

Ora, questo è il motivo per cui la gente usa EXISTS+ NOT EXISTSanziché IN+ NOT IN. Vedi anche L'uso della logica NOT in relazione agli indici per ulteriori informazioni

** Nota: unknownè uguale falsealla fine di un'espressione in una WHEREcondizione.
Mentre l'espressione viene valutata, allora non è noto
Vedi il commento di @ kgrittn qui sotto per il perché


10
Anche con il chiarimento è tecnicamente sbagliato e in un modo che potrebbe bruciare qualcuno. Ad esempio, se ritieni x <> NULLche si stia risolvendo FALSE, ti aspetteresti NOT (x <> NULL)di valutarlo TRUEe non lo fa. Entrambi valutano UNKNOWN. Il trucco è che una riga viene selezionata solo se la WHEREclausola (se presente) restituisce TRUE- una riga viene omessa se la clausola restituisce FALSEo UNKNOWN. Questo comportamento (in generale e per il NOT INpredicato in particolare) è obbligatorio per lo standard SQL.
— kgrittn,

Inoltre NULL NOT IN (some_subquery), non deve restituire la riga esterna, tranne se some_subquerynon restituisce alcuna riga. Questo è il motivo per cui il piano di esecuzione quando entrambe le colonne sono in grado di null può essere considerevolmente più costoso. Esempio di SQL Server
— Martin Smith,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.