sql >> Databasteknik >  >> RDS >> Oracle

Hur hanterar man bäst historiska uppslagsvärden i en databas?

Det finns en teknik som kallas versionshantering som har funnits i många år men som i stort sett inte fungerar av flera skäl. Det finns dock en liknande teknik som jag kallar Version Normal Form som jag har tyckt vara väldigt användbar. Här är ett exempel som använder en tabell för anställda.

Först skapas den statiska tabellen. Detta är huvudentitetstabellen och den innehåller statisk data om entiteten. Statisk data är data som inte förväntas förändras under enhetens liv, till exempel födelsedatum.

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

Det är viktigt att inse att det finns en post för varje anställd, precis som med alla sådana bord.

Sedan den tillhörande versionstabellen. Detta etablerar en 1-m relation med den statiska tabellen eftersom det kan finnas flera versioner för en anställd.

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

I versionstabellanteckningen finns ett ikraftträdandedatum men inte ett matchande fält som inte längre är i kraft. Detta beror på att när en version väl träder i kraft förblir den i kraft tills den ersätts av den efterföljande versionen. Kombinationen av ID och EffDate måste vara unik så att det inte kan finnas två versioner för samma anställd som är aktiva samtidigt, och det kan inte heller finnas ett gap mellan det att en version slutar och när nästa version startar.

De flesta frågor kommer att vilja veta den aktuella versionen av personaldata. Detta tillhandahålls genom att sammanfoga den statiska raden för medarbetaren med den version som gäller nu. Detta kan hittas med följande fråga:

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;

Detta returnerar den enda versionen som startade i det senaste. Använder olikheten <=i datumkontrollen (v2.EffDate <= NOW() ) möjliggör ikraftträdande datum i framtiden. Anta att du vet att en ny anställd kommer att börja den första dagen i nästa månad eller att en lönehöjning är planerad till den 13:e nästa månad, kan denna information infogas i förväg. Sådana "förladdade" poster kommer att ignoreras.

Låt inte underfrågan komma till dig. Alla sökfält är indexerade så resultatet är ganska snabbt.

Det finns mycket flexibilitet med denna design. Frågan ovan returnerar den senaste informationen för alla anställda, nuvarande och tidigare. Du kan kontrollera TermDate fält för att få just närvarande medarbetare. Faktum är att en hel del platser i dina appar bara är intresserade av aktuell information om nuvarande anställda, skulle den frågan ge en bra bild (utelämna den sista where klausul). Apparna behöver inte ens veta att sådana versioner finns.

Om du har ett visst datum och du vill se data som gällde vid den tidpunkten, ändra sedan v2.EffDate <= NOW() i underfrågan till v2.EffDate <= :DateOfInterest .

Mer information finns i en bildpresentation här och ett inte helt färdigt dokument här.

För att visa upp lite av designens töjbarhet, lägg märke till att det finns en IsWorking indikator i versionstabellen samt ett uppsägningsdatum i den statiska tabellen. När en anställd lämnar företaget infogas sista datum i den statiska tabellen och en kopia av den senaste versionen med IsWorking inställd på false infogas i versionstabellen.

Det är ganska vanligt att anställda lämnar ett företag ett tag och sedan anställs igen. Med bara datumet i den statiska tabellen kan posten aktiveras igen bara genom att ställa tillbaka det datumet till NULL. Men en "blick tillbaka"-fråga för varje tidpunkt då personen inte längre var anställd skulle returnera ett resultat. Det skulle inte finnas något som tydde på att de hade lämnat företaget. Men en version med IsWorking =falskt när du lämnar företaget och IsWorking =sant när du återvänder till företaget kommer att tillåta en kontroll av det värdet vid intressetillfället och ignorera anställda när de inte längre var anställd även om de återvände senare.



  1. lista över scheman med storlekar (relativa och absoluta) i en PostgreSQL-databas

  2. Microsoft Access Table Tips – Tricks och riktlinjer del 4

  3. MySQL IFNULL() Förklarat

  4. 6 sätt att lägga till ett år till ett datum i MariaDB