Hallar los movimientos ocurridos entre dos fechas (otro método)

5 comentarios

En este artículo ya habíamos visto un método para hallar todos los movimientos (compras, ventas, cobranzas, pagos, etc.) que ocurrieron entre dos fechas dadas, y si en una fecha no hubo movimientos entonces mostrarla igual pero con un total de cero.

https://firebird21.wordpress.com/2014/04/29/hallando-todas-las-ventas-entre-dos-fechas-dadas/

Ahora, veremos otro método con el cual podremos obtener los mismos resultados, gracias a la colaboración de Claudio Martín.

Aquí, lo que haremos será crear un stored procedure seleccionable que nos devolverá todas las fechas de un rango dado, y luego cuando las necesitemos mediante un LEFT JOIN o un RIGHT JOIN las obtendremos.

Este método tiene la ventaja de que el stored procedure seleccionable que escribimos es uno solo y lo podemos utilizar en multitud de ocasiones diferentes, todas las veces que necesitemos un rango de fechas.


CREATE PROCEDURE RANGO_FECHAS(
      tdFecIni DATE,
      tdFecFin DATE)
   RETURNS(
      ftdFecha DATE)
AS
   DECLARE VARIABLE ldFecha DATE;
BEGIN

   ldFecha = tdFecIni;

   WHILE (ldFecha <= tdFecFin) DO BEGIN
      ftdFecha = ldFecha;
      SUSPEND;
      ldFecha = ldFecha + 1;
   END

END;

Entonces, usando la misma tabla que en el artículo anterior, escribiríamos:

SELECT
   R.ftdFecha,
   SUM(COALESCE(M.MVC_TOTALX, 0)) AS TOTAL_VENTAS_DIA
FROM
   RANGO_FECHAS('01/01/2014', '01/07/2014') R
LEFT JOIN
   MOVIMCAB M
      ON R.ftdFecha = M.MVC_FECHAX
GROUP BY
   R.ftdFecha

Y obtendríamos este resultado:

VENTAS1

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

El cual, como puedes verificar, es exactamente igual al obtenido con el otro método. Pero la ventaja de este nuevo método es que el stored procedure seleccionable podemos usarlo siempre que necesitemos obtener todas las fechas de un rango dado.

 Conclusión:

Una de las muchas cosas buenas que tiene el Firebird es que nos permite obtener los mismos resultados usando métodos diferentes, queda a nuestro criterio elegir el que nos parece más conveniente para cada situación particular.

En este caso, podemos tener un stored procedure que cuando las necesitemos nos devolverá todas las fechas de un rango, para ello simplemente lo juntamos mediante LEFT JOIN o RIGHT JOIN a la otra tabla y listo, ya está.

Artículos relacionados:

Hallando todas las ventas entre dos fechas dadas

Entendiendo a los Stored Procedures

El índice del blog Firebird21

 

Hallando todas las ventas entre dos fechas dadas

6 comentarios

En ocasiones podríamos necesitar ver todos los movimientos (compras, ventas, cobranzas, pagos, etc.) que ocurrieron entre dos fechas dadas, pero queremos que si en una fecha no hubo movimientos nos muestre cero.

Eso no podemos resolverlo con un SELECT porque el SELECT solamente nos mostrará los movimientos ocurridos, y si una fecha no tuvo movimientos entonces no será mostrada.

La solución es escribir un stored procedure seleccionable, el cual nos dará la información que necesitamos.

Ejemplo. Ver todas las ventas realizadas entre los días 01/ENE/2014 y 07/ENE/2014

Nuestra tabla MOVIMCAB (donde registramos la cabecera de los movimientos) tiene estos datos (y varios más que ahora no nos interesan):

VENTAS1

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

Escribimos este stored procedure:

CREATE PROCEDURE VENTAS_DIARIAS(
      tdFecIni DATE,
      tdFecFin DATE)
   RETURNS(
      ftdFechax DATE,
      ftnTotalx INTEGER)
AS
   DECLARE VARIABLE ldFecha DATE;
BEGIN

   ldFecha = tdFecIni;

   WHILE (ldFecha <= tdFecFin) DO BEGIN
      ftdFechax = ldFecha;
      ftnTotalx = (SELECT SUM(MVC_TOTALX) FROM MOVIMCAB WHERE MVC_FECHAX = :ldFecha);
      ftnTotalx = COALESCE(ftnTotalx, 0);
      SUSPEND;
      ldFecha = ldFecha + 1;
   END

END;

Y como es un stored procedure seleccionable (sabemos eso porque tiene el comando SUSPEND dentro suyo) lo ejecutamos así:

SELECT
   *
FROM
   VENTAS_DIARIAS('01/01/2014', '01/07/2014')

Para que nos muestre todas las ventas ocurridas entre los días 1 de enero de 2014 y 7 de enero de 2014, agrupadas por fecha. Y este es el resultado que obtenemos:

VENTAS2

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

Donde, como puedes ver, se muestran todas las fechas del rango elegido, si en una fecha hubo ventas el total de las ventas de esa fecha y si no hubo ventas, entonces cero.

Artículos relacionados:

Entendiendo a los Stored Procedures

El índice del blog Firebird21

 

Multiple rows in singleton select

Deja un comentario

Este mensaje de error traducido significa: “hay muchas filas en el SELECT y debería haber solamente una”

Y ocurre cuando el Firebird está esperando que un SELECT devuelva una y solamente una fila pero el SELECT está devolviendo más de una fila.

Ejemplo:

UPDATE
   MiTabla
SET
   MiColumna = (SELECT MiOtraColumna FROM MiOtraTabla WHERE MiCondición)

¿Cuál es la solución?

El problema está en el SELECT entonces es allí donde se debe solucionar. Lo más sencillo es ejecutar solamente ese SELECT, ver cual es el conjunto resultado que devuelve y modificar el SELECT para que solamente devuelva una fila.

Para que un SELECT devuelva una fila y solamente una fila tenemos varias alternativas:

  1. Cambiar la condición MiCondición
  2. Usar FIRST 1
  3. Usar ROWS 1
  4. Usar DISTINCT

Conclusión:

El error ocurre cuando un SELECT devuelve más de una fila y debería devolver solamente una fila. La solución es revisar el SELECT para comprobar que es lo que devuelve y luego modificarlo para que devuelva solamente una fila.

Artículo relacionado:

El índice del blog Firebird21