Cuando escribimos un SELECT normalmente lo que obtenemos es un resultado obtenido de extraer datos de una o más tablas. En la gran mayoría de los casos eso es justamente lo que queremos pero hay circunstancias en que resultaría más conveniente que esas filas estén separadas unas de otras. Afortunadamente para nosotros el Firebird nos provee de una forma relativamente fácil de conseguir ese efecto.

Veámoslo mejor con un ejemplo:

SELECT
   CMC_FECHAX AS "Fecha de la compra",
   CMC_NRODOC AS "Factura Nº",
   CMC_EXENTA + CMC_GRAV05 + CMC_IVA005 + CMC_GRAV10 + CMC_IVA010 AS "Total Factura"
FROM
   COMPRASCAB

ADICIONAL1

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

Este es el resultado normal de un SELECT, nada raro ahí. Pero agreguémosle ahora líneas adicionales para agrupar a esas filas por fecha. Para ello necesitaremos escribir un stored procedure como el siguiente:

SET TERM ^ ;

CREATE PROCEDURE COMPRAS_AGRUPADAS
RETURNS(
   tcFechax VARCHAR(30),
   tcNroDoc VARCHAR(15),
   tnTotalx NUMERIC(16, 4))
AS
   DECLARE VARIABLE lcCCF            VARCHAR(10);
   DECLARE VARIABLE lcFechaTemporal  VARCHAR(10);
   DECLARE VARIABLE lcNroDocTemporal VARCHAR(15);
   DECLARE VARIABLE lnTotalTemporal  NUMERIC(16, 4);
   DECLARE VARIABLE lnTotFec         NUMERIC(16, 4);
BEGIN

   lcCCF = '01/01/1900';
   lnTotFec = 0;

   FOR SELECT
      CAST(CMC_FECHAX AS VARCHAR(10)),
      CMC_NRODOC,
      CMC_EXENTA + CMC_GRAV05 + CMC_IVA005 + CMC_GRAV10 + CMC_IVA010
   FROM
      COMPRASCAB
   ORDER BY
      CMC_FECHAX
   INTO
      :tcFechax,
      :tcNroDoc,
      :tnTotalx
   DO BEGIN
      IF (lcCCF = '01/01/1900') THEN
         lcCCF = tcFechax;
      IF (tcFechax <> lcCCF) THEN BEGIN
         lcFechaTemporal  = tcFechax;
         lcNroDocTemporal = tcNroDoc;
         lnTotalTemporal  = tnTotalx;
         tcFechax = 'Total del día: ' || lcCCF;
         tcNroDoc = '';
         tnTotalx = lnTotFec;
         SUSPEND;
         tcFechax = '';
         tcNroDoc = '';
         tnTotalx = 0;
         SUSPEND;
         tcFechax = lcFechaTemporal;
         tcNroDoc = lcNroDocTemporal;
         tnTotalx = lnTotalTemporal;
         SUSPEND;
         lcCCF = lcFechaTemporal;
         lnTotFec = tnTotalx;
      END ELSE BEGIN
         lnTotFec = lnTotFec + tnTotalx;
         SUSPEND;
      END
   END

END^

SET TERM ; ^

Cada vez que le asignamos valores a los parámetros de salida y luego escribimos un SUSPEND esos parámetros de salida serán enviados al SELECT. Lo que obtendremos al ejecutar a este stored procedure será lo siguiente:


SELECT * FROM COMPRAS_AGRUPADAS;

ADICIONAL2

 

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

 Como puedes ver, cuando termina cada día se muestra una nueva fila, una fila adicional, con las palabras “Total del día:”, la fecha, y el total comprado en esa fecha. Luego, se agrega otra fila que está en blanco.

O sea que a la salida normal del SELECT se le agregaron dos filas adicionales por cada vez que se cambia la fecha, una para mostrar los totales comprados en ese día y otra en blanco que solamente sirve para separación y que las filas no estén tan amontonadas.

Por supuesto que puedes agregar todas las filas adicionales que quieras, con los datos que quieras, las condiciones son las siguientes:

  1. Debes mantener los tipos de datos. Si una columna normal es de tipo carácter, en la fila adicional también será de tipo carácter. Si es numérica, también debe ser numérica, etc.
  2. El valor que tiene un parámetro de salida en el momento del SUSPEND será el valor que recibirá el SELECT

Conclusión:

Muchas veces es conveniente tener formateada la salida ya dentro de la Base de Datos para que los programadores al generar un informe no tengan que estar calculando totales, porcentajes, etc. Ya se les da todo servido para asegurarnos que todos los resultados sean idénticos, para no estar dependiendo de la capacidad del programador ni del lenguaje que utiliza (Visual FoxPro, Visual Basic, C, C++, Delphi, etc.)

Así, nos aseguramos que todos los datos estén correctos, bien formateados, y con un aspecto uniforme.

Artículo relacionado:

El índice del blog Firebird21