SQL Server: ¿Por qué la comparación nulo = valor devuelve verdadero para NOT IN?
¿Por qué la comparación devalue
anull
devuelve falso, excepto cuando se usa unNOT IN
, donde vuelve cierto?
Dada una consulta para encontrar todos los usuarios de stackoverflow quetener una publicación:
SELECT * FROM Users
WHERE UserID IN (SELECT UserID FROM Posts)
Esto funciona como se esperaba; Recibo una lista de todos los usuarios que tienen una publicación.
Ahora consulta por el inverso; encontrar todos los usuarios de stackoverflow queno lo hagas tener una publicación:
SELECT * FROM Users
WHERE UserID NOT IN (SELECT UserID FROM Posts)
Esto no devuelve registros, lo cual es incorrecto.
Datos hipotéticos dados1
Users Posts
================ ===============================
UserID Username PostID UserID Subject
------ -------- ------- ------ ----------------
1 atkins 1 1 Welcome to stack ov...
2 joels 2 2 Welcome all!
... ... ... ...
399573 gt6989b ... ...
... ... ... ...
10592 null (deleted by nsl&fbi...
... ...
Y asuma las reglas de NULL:
NULL = NULL
evalúa a desconocidoNULL <> NULL
evalúa a desconocidovalue = NULL
evalúa desconocidoSi miramos la segunda consulta, estamos interesados en encontrar todas las filas donde está el Users.UserIDno encontrado en la columna Posts.UserID. procedería lógicamente de la siguiente manera:
Verificar ID de usuario 1
1 = 1
devuelve verdadero Por lo tanto, concluimos que este usuario tiene algunas publicaciones y no las incluimos en la lista de resultadosAhora verifique el ID de usuario 2:
2 = 1
devuelve falso, así que seguimos buscando2 = 2
devuelve verdadero, por lo que concluimos que este usuario tiene algunas publicaciones y no las incluimos en la lista de resultadosAhora verifique el ID de usuario 399573
399573 = 1
devuelve falso, así que seguimos buscando399573 = 2
devuelve falso, así que seguimos buscando...399573 = null
vuelve desconocido, así que seguimos buscando...No encontramos publicaciones de UserID 399573, por lo que lo incluiríamos en la lista de resultados.
Excepto que SQL Server no hace esto. Si tiene un NULL en suin
lista, de repente encuentra una coincidencia.De repente encuentra una coincidencia. Repentinamente399573 = null
se evalúa como verdadero
¿Por qué la comparación devalue
anull
volver desconocido, excepto cuando devuelve verdadero?
Editar: sé que puedo solucionar estoabsurdo comportamiento excluyendo específicamente los nulos:
SELECT * FROM Users
WHERE UserID NOT IN (
SELECT UserID FROM Posts
WHERE UserID IS NOT NULL)
Pero no debería tener que hacerlo, por lo que puedo decir, la lógica booleana debería estar bien sin ella, de ahí mi pregunta.
$45 a46$celko ahora tiene su propia etiqueta