Valores NULL dentro de la cláusula NOT IN

Resuelto Jamie Ide asked hace 16 años • 12 respuestas

Este problema surgió cuando obtuve recuentos de registros diferentes para lo que pensé que eran consultas idénticas, una usando una not in whererestricción y la otra usando un archivo left join. La tabla en la not inrestricción tenía un valor nulo (datos incorrectos), lo que provocó que la consulta devolviera un recuento de 0 registros. Entiendo por qué, pero me vendría bien un poco de ayuda para comprender completamente el concepto.

En pocas palabras, ¿por qué la consulta A devuelve un resultado pero B no?

A: select 'true' where 3 in (1, 2, 3, null)
B: select 'true' where 3 not in (1, 2, null)

Esto fue en SQL Server 2005. También descubrí que llamar set ansi_nulls offhace que B devuelva un resultado.

Jamie Ide avatar Sep 25 '08 01:09 Jamie Ide
Aceptado

La consulta A es la misma que:

select 'true' where 3 = 1 or 3 = 2 or 3 = 3 or 3 = null

Como 3 = 3es cierto, obtienes un resultado.

La consulta B es la misma que:

select 'true' where 3 <> 1 and 3 <> 2 and 3 <> null

Cuando ansi_nullsestá activado, 3 <> nulles DESCONOCIDO, por lo que el predicado se evalúa como DESCONOCIDO y no obtiene ninguna fila.

Cuando ansi_nullsestá desactivado, 3 <> nulles verdadero, por lo que el predicado se evalúa como verdadero y se obtiene una fila.

Brannon avatar Sep 24 '2008 19:09 Brannon

NOT INdevuelve 0 registros cuando se compara con un valor desconocido

Dado que NULLes desconocido, una NOT INconsulta que contenga a NULLo NULLs en la lista de valores posibles siempre devolverá 0registros ya que no hay forma de estar seguro de que el NULLvalor no es el valor que se está probando.

YonahW avatar Sep 24 '2008 19:09 YonahW

Siempre que usa NULL, en realidad está tratando con una lógica de tres valores.

Su primera consulta devuelve resultados cuando la cláusula WHERE se evalúa como:

    3 = 1 or 3 = 2 or 3 = 3 or 3 = null
which is:
    FALSE or FALSE or TRUE or UNKNOWN
which evaluates to 
    TRUE

El segundo:

    3 <> 1 and 3 <> 2 and 3 <> null
which evaluates to:
    TRUE and TRUE and UNKNOWN
which evaluates to:
    UNKNOWN

DESCONOCIDO no es lo mismo que FALSO, puedes probarlo fácilmente llamando a:

select 'true' where 3 <> null
select 'true' where not (3 <> null)

Ambas consultas no le darán resultados.

Si DESCONOCIDO era lo mismo que FALSO, suponiendo que la primera consulta le daría FALSO, la segunda tendría que evaluarse como VERDADERO, ya que habría sido lo mismo que NO (FALSO).
Ese no es el caso.

Hay un muy buen artículo sobre este tema en SqlServerCentral .

Todo el tema de los NULL y la lógica de tres valores puede resultar un poco confuso al principio, pero es esencial comprenderlo para poder escribir consultas correctas en TSQL.

Otro artículo que recomendaría es SQL Aggregate Functions y NULL .

kristof avatar Sep 25 '2008 09:09 kristof