¡¡¡FIREBIRD 3.0 HA SIDO LIBERADO!!!

9 comentarios

¡¡¡POR FIN!!!

La noticia que tanto tiempo estuvimos esperando por fin llegó: FIREBIRD 3.0 YA ESTÁ DISPONIBLE.

Hoy 19 de abril de 2016, me enviaron un e-mail desde el Firebird Project avisándome que Firebird 3.0 ya está listo para ser descargado desde este enlace:

http://www.firebirdsql.org/en/firebird-3-0-0/

Así que a partir de ahora pueden esperar muchos artículos del blog refiriéndose a las novedades y a las mejoras que encontraremos en Firebird 3.0

El autor de este blog evaluará exhaustivamente a Firebird 3.0 pero no lo usará en nuevos proyectos hasta al menos dentro de 2 meses cuando esté razonablemente seguro de que funciona todo bien.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

 

Anuncios

Restando fechas que se encuentran en distintas filas (2)

Deja un comentario

Ya habíamos visto como conseguir restar fechas que se encuentran en distintas filas:

Restando fechas que se encuentran en distintas filas

Ahora en este artículo veremos otro método para conseguir el mismo resultado. Para ello usaremos tablas autoreferenciadas.

Una tabla autoreferenciada es una tabla que tiene un JOIN a sí misma, y es algo que puede ser muy útil a veces.

Listado 1.


CREATE GENERATOR
   GEN_NUMERAR;

UPDATE
   PRUEBA1
SET
   PRU_NUMREG = GEN_ID(GEN_NUMERAR, 1);

DROP GENERATOR
   GEN_NUMERAR;

SELECT
   T1.PRU_NUMREG,
   T1.PRU_FECINI,
   T2.PRU_FECFIN,
   T2.PRU_FECFIN - T1.PRU_FECINI AS DIFERENCIA
FROM
   PRUEBA1 T1
LEFT JOIN
   PRUEBA1 T2
      ON T1.PRU_NUMREG = T2.PRU_NUMREG - 1

Como puedes ver en el Listado 1., la primera parte es igual a la que habíamos escrito en el otro artículo, lo único que cambia es el SELECT.

Usamos un LEFT JOIN para que siempre se muestre la Fecha Inicial, haya o no haya una Fecha Final correspondiente. Podrías usar solamente JOIN si únicamente te interesan las filas que tienen una Fecha Inicial y su correspondiente Fecha Final.

Nuestra tabla PRUEBA1 tiene estas filas:

FECHA02

Captura 1.

Y después de ejecutar el Listado 1. obtendremos lo que vemos en la Captura 2.

FECHA01

Captura 2.

Artículos relacionados:

Ejemplo Nº 004 – Usando un INNER JOIN para autoreferenciar una tabla

Autoreferenciar una tabla. Algunos ejemplos

Entendiendo las tablas autoreferenciadas

Usando una tabla autoreferenciada para averiguar números consecutivos faltantes

Restando fechas que se encuentran en distintas filas

El índice del blog Firebird21

El foro del blog Firebird21

Restando fechas que se encuentran en distintas filas

Deja un comentario

Un lector del foro de este blog, preguntó si era posible restar fechas que se encuentran en distintas filas.

Restar dos fechas de distintos registros

FECHAS01

Captura 1.

La respuesta es afirmativa, pero necesitamos conocer sin equivocación posible a la fila donde se encuentra la segunda fecha.

Por eso, en este caso supondremos que se encuentra en la siguiente fila. O sea, la Fecha Inicial estará en una fila y la Fecha Final siempre estará en la siguiente fila.

¿Y cómo podemos conocer cual es la siguiente fila?

Pues numerando a las filas, de tal manera que la primera tenga el número 1, la segunda tenga el número 2, la tercera tenga el número 3, etc.

Este artículo nos muestra algunas técnicas para conseguir lo que deseamos:

Numerando las filas de un SELECT

Lo que aquí haremos (no es el único método, pero es un método que se entiende bien) es agregarle una columna a nuestra tabla. Nos quedará así:

FECHAS02

Captura 2.

PRU_NUMREG es el Número de Registro

PRU_FECINI es la Fecha Inicial

PRU_FECFIN es la Fecha Final

Luego creamos un generador (también llamado secuencia) y con un comando UPDATE numeraremos a esas filas:

Listado 1.

CREATE GENERATOR
   GEN_NUMERAR;

UPDATE
   PRUEBA1
SET
   PRU_NUMREG = GEN_ID(GEN_NUMERAR, 1);

DROP GENERATOR
   GEN_NUMERAR;

Como el generador ya no nos sirve, lo eliminamos con el comando DROP.

El contenido de nuestra tabla ahora quedará así:

FECHAS03

Captura 3.

Como tenemos a todas las filas numeradas el siguiente paso ya es muy fácil:

Listado 2:

SELECT
   T1.PRU_NUMREG,
   T1.PRU_FECINI,
   (SELECT PRU_FECFIN FROM PRUEBA1 T2 WHERE T2.PRU_NUMREG = T1.PRU_NUMREG + 1 ROWS 1),
   (SELECT PRU_FECFIN FROM PRUEBA1 T2 WHERE T2.PRU_NUMREG = T1.PRU_NUMREG + 1 ROWS 1) - T1.PRU_FECINI AS DIFERENCIA
FROM
   PRUEBA1 T1

Podemos tener a todo junto:

Listado 3.

CREATE GENERATOR
   GEN_NUMERAR;

UPDATE
   PRUEBA1
SET
   PRU_NUMREG = GEN_ID(GEN_NUMERAR, 1);

DROP GENERATOR
   GEN_NUMERAR;

SELECT
   T1.PRU_NUMREG,
   T1.PRU_FECINI,
   (SELECT PRU_FECFIN FROM PRUEBA1 T2 WHERE T2.PRU_NUMREG = T1.PRU_NUMREG + 1 ROWS 1),
   (SELECT PRU_FECFIN FROM PRUEBA1 T2 WHERE T2.PRU_NUMREG = T1.PRU_NUMREG + 1 ROWS 1) - T1.PRU_FECINI AS DIFERENCIA
FROM
   PRUEBA1 T1;

Y este será el resultado que obtendremos:

FECHAS04

Captura 4.

Que es justamente lo que queríamos conseguir: restarle a la Fecha Inicial que se encuentra en una fila la Fecha Final que se encuentra en la siguiente fila.

Desde luego que este no es el único método posible para obtener este resultado, pero es un método fácil y sencillo de entender.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Agregando filas adicionales (2)

8 comentarios

Ya hemos visto en este artículo:

Agregando filas adicionales

como podemos hacer para agregar filas al resultado de salida de nuestra consulta. Para ello escribimos un stored procedure seleccionable.

Ahora, veremos otra técnica para obtener lo que deseamos, usando una construcción del Firebird llamada CTE (Common Table Expresion).

En nuestro ejemplo, la salida tiene 18 filas. ¿Por qué? porque hay 2 filas para Países, 4 filas para Estados y 12 filas para Ciudades. En total, 18 filas.

Y esas son exactamente las filas que tiene cada una de las tablas.

Eso nos trae a la mente que podemos usar el comando UNION para unir el conjunto resultado de la tabla PAÍSES con el conjunto resultado de la tabla ESTADOS y con el conjunto resultado de la tabla CIUDADES.

Listado 1.

WITH MiUnion AS (

   SELECT
      PAI_IDENTI * 1000000 AS CIU_ORDENX,
      PAI_NOMBRE           AS CIU_NOMPAI,
      ''                   AS CIU_NOMEST,
      ''                   AS CIU_NOMBRE
   FROM
      PAISES

   UNION

   SELECT
      EST_IDEPAI * 1000000 + EST_IDENTI * 1000 AS CIU_ORDENX,
      ''                                       AS CIU_NOMPAI,
      EST_NOMBRE                               AS CIU_NOMEST,
      ''                                       AS CIU_NOMBRE
   FROM
      ESTADOS

   UNION

   SELECT
      CIU_IDEPAI * 1000000 + CIU_IDEEST * 1000 + CIU_IDENTI AS CIU_ORDENX,
      ''                                                    AS CIU_NOMPAI,
      ''                                                    AS CIU_NOMEST,
      CIU_NOMBRE
   FROM
      CIUDADES

)

SELECT
   *
FROM
   MiUnion
ORDER BY
   CIU_ORDENX

Y este es el resultado que obtenemos al ejecutar el Listado 1.

CIUDADES10

 

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

Desde luego que la columna CIU_ORDENX no es necesario mostrarla a los usuarios, se muestra en la Captura 1. para que sea más fácil entender la técnica utilizada.

Explicación:

El comando UNION nos permite agregar al resultado de una consulta el resultado de otra consulta, obteniendo así un conjunto resultado que es la suma de los anteriores.

Como nuestras tablas tienen 2 filas, 4 filas y 12 filas, al hacer las UNIONes entre ellas el resultado final tendrá sí o sí, 18 filas.

La tabla MiUnion es una tabla virtual, una tabla que solamente existe en la memoria de la computadora, o sea, es una tabla CTE.

Como MiUnion es una tabla virtual puede tener todas las columnas que se nos ocurra, inclusive podemos inventarle columnas, tal como hicimos con la columna CIU_ORDENX.

La columna CIU_ORDENX utilizamos para guardar en ella el orden en el cual deseamos que las filas sean mostradas. Aquí obtenemos sus valores en potencias de 1.000 porque suponemos que las cantidades de Países, de Estados y de Ciudades serán menos que 1.000 y que sus identificadores respectivos también siempre serán menores que 1.000. Si cualquiera de ellos pueden ser más que 1.000 entonces tendríamos que usar potencias de 10.000, de 100.000, etc.

CIU_ORDENX para un País es: Identificador_del_País * 1.000 * 1.000

CIU_ORDENX para un Estado es: Identificador_del_País * 1.000 * 1.000 + Identificador_del_Estado * 1.000

CIU_ORDENX para una Ciudad es: Identificador_del_País * 1.000 * 1.000 + Identificador_del_Estado * 1.000 + Identificador_de_la_Ciudad

Esto implica que CIU_ORDENX para un País siempre terminará con 6 ceros, para un Estado siempre terminará con 3 ceros y para una Ciudad siempre terminará entre 001 y 999.

También implica que la cantidad de Países no puede ser mayor que 999, que la cantidad de Estados no puede ser mayor que 999 y que la cantidad de Ciudades no puede ser mayor que 999. Si cualquiera de ellos pudiera ser mayor que 999 entonces en lugar de usar potencias de 1.000 habría que usar potencias de 10.000, de 100.000, etc.

Luego de haber creado a la tabla virtual MiUnion lo único que nos resta es mostrarla, ordenada según la columna virtual CIU_ORDENX, y así obtenemos el resultado deseado.

Artículos relacionados:

Usando CTE (Common Table Expresion)

Agregando filas adicionales

El índice del blog Firebird21

El foro del blog Firebird21

 

 

Agregando filas adicionales

7 comentarios

Un lector del foro de este blog hizo un pedido interesante: mostrar una consulta de una forma especial.

CIUDADES

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

O sea que se tienen 3 tablas: PAISES, ESTADOS, CIUDADES, relacionadas mediante sus identificadores, tal y como debe ser.

Pero ¿cómo hacemos para mostrar las filas de la forma pedida?

Hay varias alternativas, en este artículo mostraremos una de ellas.

La idea es agregar a la tabla de CIUDADES, dos columnas:

  • Si mostraremos el nombre del País
  • Si mostraremos el nombre del Estado

Nuestras tablas por lo tanto tendrán las siguientes estructuras:

CIUDADES2

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

CIUDADES3

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

CIUDADES4.png

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

Los datos contenidos en esas tablas podemos ver a continuación:

CIUDADES6

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

CIUDADES7

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

CIUDADES8

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

Una consulta simple sería la siguiente:

Listado 1.

SELECT
   PAI_NOMBRE,
   EST_NOMBRE,
   CIU_NOMBRE
FROM
   CIUDADES
JOIN
   PAISES
      ON CIU_IDEPAI = PAI_IDENTI
JOIN
   ESTADOS
      ON CIU_IDEPAI = EST_IDEPAI AND
         CIU_IDEEST = EST_IDENTI
ORDER BY
   CIU_IDEPAI,
   CIU_IDEEST,
   CIU_IDENTI

CIUDADES5

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

Pero eso no es lo que queremos obtener, porque los nombres de los Países y de los Estados están repetidos, y lo que queremos es verlos una sola vez.

¿Y entonces, qué hacemos?

Si nos fijamos en la Captura 1. veremos que se muestran en total 18 filas aunque en la tabla de CIUDADES solamente hay 12 filas. Eso significa que se están mostrando 6 filas más. Por lo tanto, lo que debemos hacer es agregar esas 6 filas adicionales.

¿Y cómo lo conseguimos?

Mediante una construcción del Firebird que se llama stored procedure seleccionable.

Listado 2.

CREATE PROCEDURE SP_MOSTRAR_CIUDADES
   RETURNS(
      ftcNombrePais   TYPE OF COLUMN PAISES.PAI_NOMBRE,
      ftcNombreEstado TYPE OF COLUMN ESTADOS.EST_NOMBRE,
      ftcNombreCiudad TYPE OF COLUMN CIUDADES.CIU_NOMBRE)
AS
   DECLARE VARIABLE lcNombrePais    TYPE OF COLUMN PAISES.PAI_NOMBRE;
   DECLARE VARIABLE lcNombreEstado  TYPE OF COLUMN ESTADOS.EST_NOMBRE;
   DECLARE VARIABLE lcNombreCiudad  TYPE OF COLUMN CIUDADES.CIU_NOMBRE;
   DECLARE VARIABLE lcMostrarPais   TYPE OF COLUMN CIUDADES.CIU_MOSPAI;
   DECLARE VARIABLE lcMostrarEstado TYPE OF COLUMN CIUDADES.CIU_MOSEST;
BEGIN

   FOR SELECT
      PAI_NOMBRE,
      EST_NOMBRE,
      CIU_NOMBRE,
      CIU_MOSPAI,
      CIU_MOSEST
   FROM
      CIUDADES
   JOIN
      PAISES
         ON CIU_IDEPAI = PAI_IDENTI
   JOIN
      ESTADOS
         ON CIU_IDEPAI = EST_IDEPAI AND
            CIU_IDEEST = EST_IDENTI
   ORDER BY
      CIU_IDEPAI,
      CIU_IDEEST,
      CIU_IDENTI
   INTO
      :lcNombrePais,
      :lcNombreEstado,
      :lcNombreCiudad,
      :lcMostrarPais,
      :lcMostrarEstado
   DO BEGIN
      IF (lcMostrarPais = 'T') THEN BEGIN
         ftcNombrePais   = lcNombrePais;
         ftcNombreEstado = '';
         ftcNombreCiudad = '';
         SUSPEND;
      END
      IF (lcMostrarEstado = 'T') THEN BEGIN
         ftcNombrePais   = '';
         ftcNombreEstado = lcNombreEstado;
         ftcNombreCiudad = '';
         SUSPEND;
      END
      ftcNombrePais   = '';
      ftcNombreEstado = '';
      ftcNombreCiudad = lcNombreCiudad;
      SUSPEND;
   END

END;

Explicación:

Como necesitamos agregar 6 filas lo podemos conseguir fácilmente usando un stored procedure seleccionable.

Obtenemos y colocamos en variables locales los nombres de los Países, de los Estados, de las Ciudades, y si debemos mostrar el País, y si debemos mostrar el Estado.

Luego, colocamos en los parámetros de salida los valores que deseamos sean devueltos.

Como el stored procedure es seleccionable entonces debemos usar el comando SUSPEND cada vez que deseamos devolver los parámetros de salida.

Listado 3.

SELECT
   *
FROM
   SP_MOSTRAR_CIUDADES

Un stored procedure seleccionable puede ser tratado como si fuera una tabla. Al ejecutar el Listado 3. obtendremos el siguiente resultado.

CIUDADES9

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

Que es exactamente lo que deseábamos obtener.

Artículos relacionados:

Entendiendo a los stored procedures

Agregando filas adicionales (2)

El índice del blog Firebird21

El foro del blog Firebird21