Hay ocasiones en las cuales la más eficiente forma de obtener el resultado de una consulta es a través de una tabla que se referencia a sí misma.

En el artículo:

https://firebird21.wordpress.com/2013/05/06/ejemplo-no-004-usando-un-inner-join-para-autoreferenciar-una-tabla/

ya hemos visto como lograrlo, pero ese no es el único caso.

Por ejemplo, tenemos una tabla llamada VENTASCAB (cabecera de las ventas) algunas de cuyas filas son las siguientes:

AUTO1

(si haces clic en la imagen la verás más grande)

Y lo que nos interesa ver son las ventas a los clientes a quienes les vendimos el día 21/04/2012 y también el día 22/04/2012, o sea los clientes a quienes les hemos vendido en ambos días.

Este SELECT no funcionará:

SELECT
   VTC_IDENTI,
   VTC_TIPDOC,
   VTC_NRODOC,
   VTC_FECHAX,
   VTC_IDECLI
FROM
   VENTASCAB
WHERE
   VTC_FECHAX = '21/APR/2012' AND
   VTC_FECHAX = '22/APR/2012'

Si lo ejecutamos esto será el resultado que obtendremos:

AUTO2

(si haces clic en la imagen la verás más grande)

 Correctamente nos dice que no hay datos para mostrar. ¿Por qué? porque en ninguna fila VTC_FECHAX es igual al 21 de abril y también igual al 22 de abril. En una fila VTC_FECHAX puede ser igual a una de esas fechas, pero no a ambas.

Probemos entonces de otra forma:

Este SELECT tampoco funcionará:

SELECT
   VTC_IDENTI,
   VTC_TIPDOC,
   VTC_NRODOC,
   VTC_FECHAX,
   VTC_IDECLI
FROM
   VENTASCAB
WHERE
   VTC_FECHAX = '21/APR/2012' OR
   VTC_FECHAX = '22/APR/2012'

Al ejecutarlo este es el resultado que obtenemos:

AUTO3

(si haces clic en la imagen la verás más grande)

 Que tampoco es lo que queremos porque nos muestra los clientes a quienes le hemos vendido o el 21 de abril o el 22 de abril o ambos días. Pero a nosotros no nos interesan los clientes a quienes solamente les hemos vendido el 21 de abril ni nos interesan los clientes a quienes solamente les hemos vendido el 22 de abril. Los que nos interesan son los clientes a quienes les hemos vendido en ambos días y el SELECT anterior nos muestra a más clientes de los que necesitamos.

Entonces ¿cómo resolvemos este problema?

Mediante una autorreferencia a la tabla VENTASCAB, como se ve en el siguiente listado:

SELECT
   DISTINCT
   V1.VTC_IDENTI,
   V1.VTC_TIPDOC,
   V1.VTC_NRODOC,
   V1.VTC_FECHAX,
   V1.VTC_IDECLI
FROM
   VENTASCAB V1
JOIN
   VENTASCAB V2
      ON V1.VTC_CODSUC = V2.VTC_CODSUC AND
         V1.VTC_IDECLI = V2.VTC_IDECLI
WHERE
   ((V1.VTC_FECHAX = '21/APR/2012' AND V2.VTC_FECHAX = '22/APR/2012') OR
   (V1.VTC_FECHAX = '22/APR/2012' AND V2.VTC_FECHAX = '21/APR/2012'))

Al ejecutar este SELECT esto será lo que obtendremos:

AUTO5

(si haces clic en la imagen la verás más grande)

 Que es justamente lo que estábamos necesitando. Aquí podemos ver que al cliente con Identificador 348 le hemos hecho cuatro ventas el día 21 de abril y una venta el día 22 de abril. Y es el único cliente al cual le hemos vendido en ambos días.

¿Cuándo debemos autorreferenciar una tabla?

Cuando la respuesta está en ella y no se soluciona ni con AND ni con OR.

Artículos relacionados:

Usando un INNER JOIN para autoreferenciar una tabla

El índice del blog Firebird21

Anuncios