Ver Mensaje Individual
  #5  
Antiguo 22-07-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Reputación: 30
jachguate Va por buen camino
Cool

El problema aqui es que no has entendido la lógica de tres estados que usa SQL.

Trataré de explicarla de manera breve usando tu caso como ejemplo, puesto que no dispongo ahora de un vínculo a un artículo serio y bien redactado. De antemano me disculpo por cualquier error que pueda cometer en la forma, puesto que mi oficio no es el de escritor.

Lógica de 3 estados en SQL
by jachguate.

En SQL cualquier variable, incluyendo las booleanas puede tener valor NULL.

Cuando haces comparaciones, que devuelven un valor booleano, estas pueden devolver Verdadero, Falso o también NULL, que es algo a lo que no estamos acostumbrados cuando comenzamos con SQL y que regularmente ocasiona este tipo de confusiones.

Revisemos primero que significa el valor NULL: Desconocido o ausencia de valor.

Así, la comparación de desigualdad que estas aplicando sigue la siguiente lógica:

Código:
Comparando Presente <> T

Cod Nombre Presente Comparación
--- ------ -------- -----------
  1 Paco   T        Falso
  2 Pepe   F        Verdadero
  3 Luis   NULL     NULL
  4 Mara   NULL     NULL
  5 Rosa   NULL     NULL
  6 Tono   F        Verdadero
Se incluirán en el resultado solamente aquellos registros cuya comparación devuelva Verdadero (solamente los que tienen Falso).

Esto tiene sentido, dado que NULL es desconocido. SQL piensa de esta forma:

Es Desconocido(null) Diferente de Verdadero, pues no lo se, entonces el resultado es Desconocido(null). Dado que desconocido podria ser verdadero o falso.

Por eso, tampoco podrias comparar así:
WHERE Presente="F" or Presente="NULL"

pues obtendrias exactamente el mismo resultado... dado que tampoco sabemos si desconocido es igual a desconocido. Para ello, SQL ha inventado el operador is null.

Así, la consulta adecuada sería:

Código SQL [-]
Select *
  from MiTabla
 where Presente <> 'T'
    or Presente is null;

Una forma de sortear esto también es valerse de una función como coalesceque regularmente devuelve el primer valor no nulo de sus parámetros, pero no existe en todos los motores:

Código SQL [-]
Select *
  from MiTabla
 where coalesce(Presente, 'F') <> 'T'

Así, coalesce devolverá el valor de presente, o 'F' en caso que presente sea Null y la condición se cumplirá tal como deseas. En oracle, por ejemplo, la función a usar sería nvl.

Te recomiendo consultar la documentación de tu motor para ver si hay alguna función equivalente que esté disponible para vos.

También te recomiendo investigar un poco mas sobre el comportamiento de los valores nulos en general, pues probablemente te sorprenda que 5 + null => null, dado que 5 + desconocido => desconocido.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita