Cuando debemos responder una consulta negativa podemos equivocarnos y mostrar resultados erróneos, hay que prestarle mucha atención a esos casos.

¿Cuándo una consulta es negativa?

Cuando en ella usamos el operador NOT o el operador <>

Veamos un ejemplo:

Tenemos una tabla de VENDEDORES y una tabla de VENTAS, en la cual registramos entre otras cosas el Identificador del vendedor que realizó la venta.

PROBLEMA1

Captura 1. Si haces clic en la imagen la verás más grande

PROBLEMA2

Captura 2. Si haces clic en la imagen la verás más grande

En la columna VEN_IDEVEN se guarda el Identificador del vendedor que realizó la venta.

Consulta positiva. ¿Cuáles vendedores vendieron el día 2 de enero de 2015?

Como esta es una consulta positiva (o sea que no se usa NOT ni <> en ella) podríamos simplemente responderla así:

SELECT
   VEN_IDEVEN
FROM
   VENTAS
WHERE
   VEN_FECHAX = '2015/01/02'

PROBLEMA3

Captura 3. Si haces clic en la imagen la verás más grande

O mejor aún, para que no se repitan los identificadores de los vendedores que realizaron más de una venta, de esta manera:

SELECT
   DISTINCT
   VEN_IDEVEN
FROM
   VENTAS
WHERE
   VEN_FECHAX = '2015/01/02'

PROBLEMA4

Captura 4. Si haces clic en la imagen la verás más grande

Entonces, el Identificador de cada vendedor aparecerá una sola vez.

Todo bien hasta aquí.

Consulta negativa. ¿Cuáles vendedores no vendieron el día 2 de enero de 2015?

Es muy tentador pensar que esta consulta se responderá si reemplazamos el símbolo de = por el símbolo de <> en el SELECT anterior. Con eso tendremos la respuesta buscada, ¿verdad?

Falso.

Si escribimos esta consulta:

SELECT
   DISTINCT
   VEN_IDEVEN
FROM
   VENTAS
WHERE
   VEN_FECHAX <> '2015/01/02'

Donde lo único que hemos hecho fue cambiar el símbolo = por el símbolo <> lo que obtendremos será esto:

PROBLEMA5

Captura 5. Si haces clic en la imagen la verás más grande

La cual, como podemos ver no es la respuesta correcta.

¿Por qué no es la respuesta correcta?

Porque el vendedor cuyo Identificador es 1 (SERGIO) no es mostrado. Y SERGIO tampoco ha vendido, así que debería mostrarse su Identificador.

¿Cuál es la razón de nuestro error?

Que estamos usando la tabla equivocada para responder la consulta. En la tabla VENTAS se guardan los identificadores de los vendedores que realizaron ventas, por lo tanto responder consultas positivas es muy sencillo. Pero en esa tabla no se guardan los identificadores de los vendedores que no realizaron ventas y eso implica que no puede usarse para responder consultas negativas.

Además, si has entendido bien lo que sucede en estos casos habrás notado que para responder una consulta positiva si se encuentra una fila, aunque sea una sola fila, que cumpla la condición ya aparecerá en el conjunto resultado del SELECT, pero para las consultas negativas hay que recorrer toda la tabla y aún así no es seguro que siempre se obtenga la respuesta correcta.

¿Cuál es la solución?

Usar como tabla principal la tabla de VENDEDORES, no la tabla de VENTAS, y filtrar por los vendedores que no han vendido en esa fecha. Entonces tendríamos algo como:

SELECT
   T1.VEN_IDENTI
FROM
   VENDEDORES T1
WHERE
   NOT EXISTS(SELECT 
                 T2.VEN_IDEVEN 
              FROM 
                 VENTAS T2 
              WHERE 
                 T2.VEN_IDEVEN = T1.VEN_IDENTI AND 
                 T2.VEN_FECHAX = '2015/01/02')

PROBLEMA6

Captura 6. Si haces clic en la imagen la verás más grande

Aquí sí hemos obtenido la respuesta correcta, porque al usar la función EXISTS() podemos saber si un vendedor ha realizado alguna venta en la fecha 2 de enero de 2015.

Conclusión:

Si en nuestro SELECT usamos el operador NOT o el operador <> debemos prestarle mucha atención al resultado obtenido porque muchas veces no es el que deseamos obtener.

Es bastante frecuente consultar a la tabla equivocada porque se tiene el preconcepto de que si una consulta positiva da un cierto resultado, entonces al cambiarla por una consulta negativa se tendrá el resultado inverso y eso no siempre es cierto.

En general, las consultas negativas se responden usando la función [NOT] EXISTS() o el operador [NOT] IN. Si no usas ninguno de ellos es muy probable que tu consulta negativa sea errónea. Cuidado con ese punto.

Artículos relacionados:

Consultando datos que NO EXISTEN en una tabla

El índice del blog Firebird21

El foro del blog Firebird21

Anuncios