sql >> Base de Datos >  >> RDS >> Oracle

¿Cómo administrar mejor los valores de búsqueda históricos en una base de datos?

Existe una técnica llamada control de versiones que existe desde hace muchos años, pero que en gran medida no funciona por varias razones. Sin embargo, existe una técnica similar a la que llamo Version Normal Form que he encontrado muy útil. Aquí hay un ejemplo usando una tabla de Empleados.

Primero, se crea la tabla estática. Esta es la tabla de entidad principal y contiene datos estáticos sobre la entidad. Los datos estáticos son datos que no se espera que cambien durante la vida de la entidad, como la fecha de nacimiento.

create table Employees(
  ID        int  auto_generated primary key,
  FirstName varchar( 32 ),
  Hiredate  date not null,
  TermDate  date,            -- last date worked
  Birthdate date,
  ...              -- other static data
);

Es importante darse cuenta de que hay una entrada para cada empleado, al igual que con cualquier tabla de este tipo.

Luego, la tabla de versiones asociada. Esto establece una relación de 1 m con la tabla estática, ya que podría haber varias versiones para un empleado.

create table Employee_versions(
  ID         int   not null,
  EffDate    date  not null,
  char( 1 )  IsWorking not null default true,
  LastName   varchar( 32 ),    -- because employees can change last name
  PayRate    currency not null,
  WorkDept   int   references Depts( ID ),
  ...,              -- other changable data
  constraint PK_EmployeeV primary key( ID, EffDate )
);

En la nota de la tabla de versiones hay una fecha de vigencia, pero no un campo coincidente que ya no sea efectivo. Esto se debe a que una vez que una versión entra en vigencia, permanece vigente hasta que se reemplaza por la versión posterior. La combinación de ID y EffDate debe ser única, por lo que no puede haber dos versiones para el mismo empleado que estén activas al mismo tiempo, ni puede haber una brecha entre el momento en que finaliza una versión y el momento en que comienza la siguiente.

La mayoría de las consultas querrán saber la versión actual de los datos de los empleados. Esto se proporciona al unir la fila estática del empleado con la versión que está vigente ahora. Esto se puede encontrar con la siguiente consulta:

select  ...
from    Employees e
join    Employee_versions v1
    on  v1.ID = e.ID
    and v1.EffDate =(
        select  Max( v2.EffDate )
        from    EmployeeVersions v2
        where   v2.ID = v1.ID
            and v2.EffDate <= NOW()
    )
where  e.ID = :EmpID;

Esto devuelve la única versión que comenzó en el pasado más reciente. Usando la desigualdad <=en la verificación de fecha (v2.EffDate <= NOW() ) permite fechas efectivas en el futuro. Suponga que sabe que un nuevo empleado comenzará el primer día del próximo mes o un aumento de sueldo está programado para el día 13 del próximo mes, estos datos se pueden insertar con anticipación. Tales entradas "precargadas" serán ignoradas.

No dejes que la subconsulta te afecte. Todos los campos de búsqueda están indexados por lo que el resultado es bastante rápido.

Hay mucha flexibilidad con este diseño. La consulta anterior devuelve los datos más recientes de todos los empleados, presentes y pasados. Puede verificar el TermDate campo para obtener sólo los empleados presentes. De hecho, dado que muchos lugares de sus aplicaciones solo estarán interesados ​​en la información actual de los empleados actuales, esa consulta sería una buena vista (omita el where final cláusula). No es necesario que las aplicaciones sepan que existen tales versiones.

Si tiene una fecha en particular y desea ver los datos que estaban vigentes en ese momento, cambie v2.EffDate <= NOW() en la subconsulta a v2.EffDate <= :DateOfInterest .

Se pueden encontrar más detalles en una presentación de diapositivas aquí y en un documento no completo aquí.

Para mostrar un poco de la extensibilidad del diseño, observe que hay un IsWorking indicador en la tabla de versiones, así como una fecha de terminación en la tabla estática. Cuando un empleado deja la empresa, se inserta la última fecha en la tabla estática y una copia de la última versión con IsWorking establecido en false se inserta en la tabla de versiones.

Es bastante común que los empleados dejen una empresa por un tiempo y luego sean contratados nuevamente. Con solo la fecha en la tabla estática, la entrada se puede activar nuevamente simplemente configurando esa fecha nuevamente en NULL. Pero una consulta de "mirar hacia atrás" para cualquier momento en que la persona ya no era un empleado arrojaría un resultado. No habría ninguna indicación de que habían dejado la empresa. Pero una versión con IsWorking =falso al dejar la empresa y IsWorking =verdadero al regresar a la empresa permitirá verificar ese valor en el momento de interés e ignorar a los empleados cuando ya no eran empleados, incluso si regresaron más tarde.