Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como gerenciar melhor os valores de pesquisa históricos em um banco de dados?


Existe uma técnica chamada versionamento que existe há muitos anos, mas é praticamente impraticável por vários motivos. No entanto, existe uma técnica semelhante que chamo de Versão Normal de Forma que considero muito útil. Aqui está um exemplo usando uma tabela Employees.

Primeiro, a tabela estática é criada. Esta é a tabela de entidade principal e contém dados estáticos sobre a entidade. Dados estáticos são dados que não devem ser alterados durante a vida da entidade, como data de nascimento.
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
);

É importante perceber que há uma entrada para cada funcionário, assim como em qualquer tabela.

Em seguida, a tabela de versão associada. Isso estabelece um relacionamento de 1 m com a tabela estática, pois pode haver várias versões para um funcionário.
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 )
);

Na observação da tabela de versões, há uma data de vigência, mas não um campo correspondente que não está mais em vigor. Isso ocorre porque uma vez que uma versão entra em vigor, ela permanece em vigor até ser substituída pela versão subsequente. A combinação de ID e EffDate deve ser única, de modo que não pode haver duas versões para o mesmo funcionário que estejam ativas ao mesmo tempo, nem pode haver um intervalo entre o momento em que uma versão termina e quando a próxima versão é iniciada.

A maioria das consultas desejará saber a versão atual dos dados do funcionário. Isso é fornecido pela união da linha estática do funcionário com a versão que está em vigor agora. Isso pode ser encontrado com a seguinte 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;

Isso retorna a única versão iniciada no passado mais recente. Usando a desigualdade <=na verificação de data (v2.EffDate <= NOW() ) permite datas efetivas no futuro. Suponha que você saiba que um novo funcionário começará no primeiro dia do próximo mês ou um aumento de salário está agendado para o dia 13 do próximo mês, esses dados podem ser inseridos com antecedência. Essas entradas "pré-carregadas" serão ignoradas.

Não deixe a subconsulta chegar até você. Todos os campos de pesquisa são indexados para que o resultado seja bastante rápido.

Há muita flexibilidade com este design. A consulta acima retorna os dados mais recentes de todos os funcionários, atuais e passados. Você pode verificar o TermDate campo para obter apenas funcionários presentes. Na verdade, como muitos lugares em seus aplicativos estarão interessados ​​apenas nas informações atuais dos funcionários atuais, essa consulta daria uma boa visualização (omitir o where final cláusula). Não há necessidade de os aplicativos saberem que essas versões existem.

Se você tiver uma data específica e quiser ver os dados que estavam em vigor naquele momento, altere o v2.EffDate <= NOW() na subconsulta para v2.EffDate <= :DateOfInterest .

Mais detalhes podem ser encontrados em uma apresentação de slides aqui e em um documento não totalmente concluído aqui.

Para mostrar um pouco da extensibilidade do design, observe que há um IsWorking indicador na tabela de versões, bem como uma data de término na tabela estática. Quando um funcionário sai da empresa, a última data é inserida na tabela estática e uma cópia da versão mais recente com IsWorking definido como false é inserido na tabela de versões.

É bastante comum que os funcionários deixem uma empresa por um tempo e sejam contratados novamente. Com apenas a data na tabela estática, a entrada pode ser ativada novamente apenas definindo essa data de volta para NULL. Mas uma consulta "retrospectiva" para qualquer momento em que a pessoa não fosse mais um funcionário retornaria um resultado. Não haveria nenhuma indicação de que eles haviam deixado a empresa. Mas uma versão com IsWorking =false ao sair da empresa e IsWorking =true ao retornar à empresa permitirá a verificação desse valor no momento do interesse e ignorará os funcionários quando deixaram de ser funcionários mesmo que tenham retornado posteriormente.