Unidad 6. Las subconsultas (III)


Si combinamos el operador IN con NOT obtenemos el operador NOT IN.

<expresion> NOT IN subconsulta

Devuelve TRUE si el valor de la expresión no está en la lista de valores devueltos por la subconsulta.

SELECT *

FROM empleados

WHERE oficina NOT IN (SELECT oficina

					FROM oficinas 

					WHERE region = 'Este');

Devuelve los empleados cuya oficina no esté en la lista generada por la subconsulta, es decir empleados que trabajan en oficinas que no son del Este.

OJO con NOT IN.
Hay que tener especial cuidado con los valores nulos cuando utilizamos el operador NOT IN porque el resultado obtenido no siempre será el deseado por ejemplo:

* En la consulta anterior no salen los empleados que no tienen oficina ya que para esos empleados la columna oficina contiene NULL por lo que no se cumple el NOT IN.

* Si la subconsulta no devuelve ninguna fila, la condición se cumplirá para todas las filas de la consulta externa, en este caso todos los empleados.

* Si la subconsulta devuelve algún valor NULL, la condición NOT IN es NULL lo que nos puede ocasionar algún problema.
Por ejemplo, queremos obtener las oficinas que no están asignadas a ningún empleado.


SELECT *

FROM Oficinas

WHERE oficina NOT IN (SELECT oficina

                      FROM empleados);

Esta consulta no devuelve ninguna fila cuando sí debería ya que hay oficinas que nos están asignadas a ningún empleado. El problema está en que la columna oficina de la tabla empleados admite nulos por lo que la subconsulta devuelve valores nulos en todos los empleados que no están asignados a ninguna oficina. Estos valores nulos hacen que no se cumpla el NOT IN. La solución pasa por eliminar estos valores molestos:

SELECT *

FROM Oficinas

WHERE oficina NOT IN (SELECT oficina

                      FROM empleados

                      WHERE oficina IS NOT NULL);

En el primer ejemplo no tenemos ese problema porque la columna oficina en oficinas no admite nulos.

A diferencia de IN, NOT IN no siempre puede resolverse con una composición:

SELECT numemp AS [IN]

FROM empleados

WHERE numemp IN (SELECT rep

					FROM pedidos

					WHERE fab = 'ACI');

Se puede resolver con una composición:


SELECT DISTINCT empleados.numemp AS [=]

FROM Empleados INNER JOIN pedidos ON numemp = rep

WHERE fab = 'ACI'; 

En este caso, como un empleado puede tener varios pedidos hay que añadir DISTINCT para eliminar las repeticiones de empleados (si un empleado tiene varios pedidos de ACI aparecería varias veces).

Sin embargo esta sentencia con NOT IN, queremos los empleados que no tienen pedidos de ACI:

SELECT numemp AS [NOT IN]

FROM empleados

WHERE numemp NOT IN (SELECT rep

					FROM pedidos

					WHERE fab = 'ACI');

No se puede resolver con una composición:

SELECT DISTINCT empleados.numemp AS [<>]

FROM Empleados INNER JOIN pedidos ON numemp = rep

WHERE fab <> 'ACI'; 

Esta consulta devuelve los empleados que tienen pedidos que no son de ACI, pero un empleado puede tener pedidos de ACI y otros de otros fabricantes y por estos otros saldría en el resultado cuando sí tiene pedidos de ACI y no debería salir.
Hay que tener mucho cuidado con este tipo de preguntas.

Para practicar puedes realizar este Ejercicio El operador IN con subconsulta.

Febrero-2010
Pág. 6.3

Atrás  Inicio  Adelante





Página inicial  Cursos Informática Gratuitos

Síguenos en:   Facebook       Sobre aulaClic            Política de Cookies


© aulaClic S.L. Todos los derechos reservados. Prohibida la reproducción por cualquier medio.