sql >> Database >  >> RDS >> Oracle

Hoe kunt u historische opzoekwaarden in een database het beste beheren?

Er is een techniek die versiebeheer wordt genoemd en die al vele jaren bestaat, maar om verschillende redenen grotendeels onwerkbaar is. Er is echter een vergelijkbare techniek die ik Version Normal Form noem en die ik erg nuttig heb gevonden. Hier is een voorbeeld waarin een tabel Werknemers wordt gebruikt.

Eerst wordt de statische tabel gemaakt. Dit is de hoofdentiteitstabel en deze bevat statische gegevens over de entiteit. Statische gegevens zijn gegevens die naar verwachting niet zullen veranderen tijdens de levensduur van de entiteit, zoals de geboortedatum.

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
);

Het is belangrijk om te beseffen dat er voor elke medewerker één item is, net als bij elke dergelijke tabel.

Dan de bijbehorende versietabel. Dit zorgt voor een relatie van 1 m met de statische tabel, aangezien er verschillende versies voor een werknemer kunnen zijn.

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 )
);

Opmerking in de versietabel is dat er een ingangsdatum is, maar geen overeenkomend veld dat niet langer van kracht is. Dit komt omdat zodra een versie van kracht wordt, deze van kracht blijft totdat deze wordt vervangen door de volgende versie. De combinatie van ID en EffDate moet uniek zijn, zodat er niet twee versies voor dezelfde werknemer tegelijkertijd actief kunnen zijn, en er mag ook geen tijd zijn tussen het moment dat de ene versie eindigt en het moment waarop de volgende versie start.

De meeste vragen willen de huidige versie van werknemersgegevens weten. Dit wordt gedaan door de statische rij voor de werknemer te koppelen aan de versie die nu van kracht is. Dit is te vinden met de volgende zoekopdracht:

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;

Dit retourneert de enige echte versie die in het meest recente verleden is gestart. De ongelijkheid <=gebruiken in de datumcontrole (v2.EffDate <= NOW() ) zorgt voor ingangsdatums in de toekomst. Stel dat u weet dat een nieuwe werknemer op de eerste dag van de volgende maand begint of dat er een loonsverhoging gepland is voor de 13e van de volgende maand, dan kunnen deze gegevens van tevoren worden ingevoerd. Dergelijke "vooraf geladen" items worden genegeerd.

Laat de subquery je niet te pakken krijgen. Alle zoekvelden zijn geïndexeerd, dus het resultaat is vrij snel.

Er is veel flexibiliteit met dit ontwerp. De bovenstaande query retourneert de laatste gegevens van alle werknemers, heden en verleden. Je zou de TermDate . kunnen controleren veld om net aanwezige medewerkers te krijgen. Aangezien een groot aantal plaatsen in uw apps alleen geïnteresseerd zijn in de huidige informatie van huidige werknemers, zou die zoekopdracht een goed beeld geven (laat de laatste where weg clausule). De apps hoeven niet eens te weten dat dergelijke versies bestaan.

Als u een bepaalde datum heeft en u wilt de gegevens zien die op dat moment van kracht waren, wijzig dan de v2.EffDate <= NOW() in de subquery naar v2.EffDate <= :DateOfInterest .

Meer details zijn hier te vinden in een diapresentatie en hier in een niet helemaal voltooid document.

Om een ​​beetje te pronken met de uitbreidbaarheid van het ontwerp, merk op dat er een IsWorking is indicator in de versietabel en een einddatum in de statische tabel. Wanneer een werknemer het bedrijf verlaat, wordt de laatste datum ingevoegd in de statische tabel en een kopie van de nieuwste versie met IsWorking ingesteld op false wordt ingevoegd in de versietabel.

Het komt vrij vaak voor dat werknemers een bedrijf een tijdje verlaten en dan weer worden aangenomen. Met alleen de datum in de statische tabel, kan de invoer opnieuw worden geactiveerd door die datum weer op NULL te zetten. Maar een "terugblik"-query voor elk moment waarop de persoon niet langer een werknemer was, zou een resultaat opleveren. Er zou geen indicatie zijn dat ze het bedrijf hadden verlaten. Maar een versie met IsWorking =false bij het verlaten van het bedrijf en IsWorking =waar bij terugkeer naar het bedrijf zal een controle van die waarde mogelijk maken op het moment van interesse en werknemers negeren wanneer ze geen werknemer meer waren, zelfs als ze later terugkwamen.



  1. Inleiding tot SQL

  2. Hoe PostgreSQL-query's loggen?

  3. Oracle 12cR2 nu in bèta

  4. UPDATE meerdere tabellen in MySQL met LEFT JOIN