Una de las operaciones más habituales (por no decir la operación más habitual) al trabajar con tablas versionadas (Fecha Desde y Fecha Hasta), es decir, con tablas que almacenan datos históricos, es consultar la versión válida a una fecha dada. Poniendo el ejemplo bancario de las Cuentas Corrientes y los Titulares, sería el caso de obtener la versión válida de un Titular específico a una fecha dada. Suponiendo una aplicación de facturación, este tipo de consultas se hace de vital importancia, ya que nos interesará conocer la información del Cliente a fecha de Factura (por poner uno de los muchos casos de uso).
Este tipo de consultas son muy habituales en sistemas operacionales o transaccionales (OLTP) en que se utilicen intensamente tablas versionadas. Sin embargo, en entornos de Business Intelligence (BI) y Data Warehouse (DW) también es necesario utilizar este tipo de consultas SQL cuando el origen de datos son tablas versionadas, resultando principalmente útil para entornos Reporting (en entornos OLAP quizás sea menos importante, ya que podemos utilizar Claves Subrogadas que ocultaremos en las tablas de dimensión, mostrando el nivel correspondiente a la Clave de Negocio). La diferencia en la problemática entre los entornos OLTP y Reporting, está en que en OLTP habitualmente accederemos a una única fila (posicionándonos en la fecha correcta, es decir, tomando la versión de la fecha), mientras que en Reporting suele tratarse más con consultas másivas (múltiples filas) posicionándose a una fecha también (ej: obtener la Cartera de Clientes a fecha de cierre del mes vencido).
Si no estuviésemos trabajando con tablas versionadas (ni con ningún otro sistema de histórico), para obtenerla la información de un Titular (si tomamos el ejemplo bancario de las Cuentas Corrientes y los Titulares), la consulta SQL se limitaría a una sencilla cláusula WHERE en la que filtrar por la Clave de Negocio (Business Key ó BK), como pudiera ser el código del Titular (ej: TitularId). A continuación se muestra un ejemplo de una consulta SQL:
SELECT * FROM dbo.Titulares WHERE TitularId = @TitularId |
Sin embargo, al utilizar tablas versionadas (con Fecha Desde y Fecha Hasta), para cada Titular pueden existir múltiples filas, cada una de las cuales representa una versión distinta del mismo Titular, es decir, la información correspondiente a dicho Titular correspondiente al periodo comprendido entre la Fecha Desde y la Fecha Hasta de dicha fila. Por ello, siempre se suelen consultar las tablas versionadas a una fecha. La forma de construir la cláusula WHERE depende del Modelo de Versionado utilizado en la tabla que estamos consultando, lo cual determinará qué operadores de comparación utilizar, etc. Tomando como premisa la utilización del Modelo de Versionado presentado anteriormente en este Artículo, la consulta SQL a desarrollar para posicionarnos a un fecha en una tabla versionada, sería similar al siguiente ejemplo:
SELECT * FROM dbo.Titulares WHERE TitularId = @TitularId AND FecDesde <= @FechaConsulta AND FecHasta > @FechaConsulta |
Insisto en que la utilización de los operadores de comparación correctos es fundamental. Por ejemplo, no podremos utilizar el operador BETWEEN (ej: @FechaConsulta BETWEEN FecDesde AND FecHasta), ya que es equivalente a FecDesde <= @FechaConsulta AND FecHasta >= @FechaConsulta, expresión que NO es válida para nuestra caso. Aquí, la elección incorrecta de operadores de comparación se paga muy caro, pues la consulta SQL no devolverá lo que tenía que devolver (malo ;-).
Para comprobar o validar nuestra consulta, podemos utilizar el Gráfico de Línea de Tiempo. Así, podemos tomar como Fecha de la Consulta una de las líneas rojas verticales discontinuas (ej: la primera de las líneas, la a), y seguidamente comprobar la consulta contra los diferentes casos de versiones, y en cada caso sustituir la Fecha Desde y Fecha Hasta (valores c y d) de la versión, y comprobar si se satisface correctamente o no nuestra consulta. Para simplificar este trabajo, podemos tomar la expresión lógica c<=a & d>a, y comprobar dicha expresión sobre el Gráfico de Línea de tiempo. El resultado es muy sencillo: sólo se debe satisfacer dicha expresión lógica (es decir, debe devolver Verdadero dicha expresión), para aquellas versiones válidas en la Fecha de la Consulta, y en el resto de los casos, la expresión no debe satisfacerse (es decir, debe devolver Falso).
Para complicar un poco más nuestra consulta, vamos a tomar como ejemplo una tabla versionada de Titulares que también incluye los campos Fecha Alta y Fecha Baja, de tal modo, que deseamos realizar una consulta SQL que devuelva la versión válida de un Titular en un momento del tiempo, sólo y exclusivamente si el Titular estaba dado de Alta en dicho momento del tiempo. En este caso, la consulta SQL que deseamos es similar a la anterior, pero deberemos fortalecer la cláusula WHERE (es decir, añadir una conjunción, osea, una cláusula AND) como se muestra en el siguiente ejemplo:
SELECT * FROM dbo.Titulares WHERE TitularId = @TitularId AND FecDesde <= @FechaConsulta AND FecHasta > @FechaConsulta AND FecAlta <= @FechaConsulta AND FecBaja > @FechaConsulta |
Con esto, habremos conseguido nuestro objetivo, obteniendo la versión deseada, sólo y exclusivamente si dicha versión tenía vigencia a la fecha de consulta.