Cuando usamos el operador not in
sobre el resultado de una subconsulta es necesario ser precavido ante la posible presencia de valores nulos en ese resultado.
Ya deberías saber que, si el conjunto de valores sobre el que se aplica not in
contiene algún valor null
, la condición que estemos evaluando no se verificará nunca
Para ilustrarlo, consideremos este ejemplo (te recomiendo que lo pruebes usando los enlaces a DB Fiddle que se proporcionan). Disponemos de una tabla de clientes de un comercio con la siguiente información:
Cliente +----+-------------+--------+---------+ | id | nombre | genero | ciudad | +----+-------------+--------+---------+ | 1 | Ana Abad | M | Logroño | | 2 | Bea Bez | M | Logroño | | 3 | Carlos Cruz | H | Logroño | | 4 | Diego Díaz | H | NULL | | 5 | Eva Ena | M | Madrid | +----+-------------+--------+---------+
Queremos obtener un listado de clientas (mujeres) que viven en ciudades en las que no vive ningún cliente varón. Para ello planteamos una consulta que, a priori, parece correcta y que debería mostrar la fila de la cliente número 5.
select *
from Cliente
where genero='M'
and ciudad not in (select ciudad
from Cliente
where genero='H');
Pero el resultado es que no hay resultados.
La explicación de este fenómeno está en que el resultado de la subconsulta son estos dos valores ('Logroño', null)
. Debido al null
ahí contenido, ninguna de las comprobaciones ciudad not in ('Logroño', null)
de las tuplas de clientas mujeres es evaluada a true
. En el caso de las que viven el Logroño, es obvio que la condición es falsa; pero incluso en el caso de la clienta de Madrid, debido al valor null
no se puede asegurar que la condición sea cierta.
¿Qué se puede hacer entonces? Lo que siempre aconsejamos ante una consulta que requiera usar not in
es hacer alguna de estas dos cosas:
- Asegurarse de que los valores devueltos por la subconsulta son de alguna clave. Eso impedirá que aparezcan valores nulos
- Evitar la presencia de nulos incluyendo alguna cláusula
is not null
- No usar
not in
, siempre que se te ocurra otra solución que sea sencilla.
En nuestro ejemplo, podríamos haber salido del paso con esta consulta
select *
from Cliente
where genero='M'
and ciudad not in (select ciudad
from Cliente
where genero='H' and ciudad is not null);
Rizando el rizo
Un purista podría decir que el resultado de la consulta anterior debería ser una tabla vacía. Y, la verdad, no le faltaría razón, ya que como no sabemos donde vive el cliente 'Diego Díaz' no podríamos afirmar con seguridad que las mujeres no vivan en su ciudad (sea la que sea esta). Por eso, hubiese sido mejor enunciar la consulta de esta manera: Listado de clientas (mujeres) que viven en ciudades en las que se sepa que no vive ningún cliente varón.
No hay comentarios:
Publicar un comentario