Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie verwaltet man am besten historische Suchwerte in einer Datenbank?

Es gibt eine Technik namens Versionierung, die es seit vielen Jahren gibt, die aber aus mehreren Gründen weitgehend nicht praktikabel ist. Es gibt jedoch eine ähnliche Technik, die ich Version Normal Form nenne und die ich als sehr nützlich empfinde. Hier ist ein Beispiel mit einer Employees-Tabelle.

Zuerst wird die statische Tabelle erstellt. Dies ist die Hauptentitätstabelle und enthält statische Daten über die Entität. Statische Daten sind Daten, von denen nicht erwartet wird, dass sie sich während der Lebensdauer der Entität ändern, wie z. B. das Geburtsdatum.

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 ist wichtig zu wissen, dass es genau wie bei jeder solchen Tabelle einen Eintrag für jeden Mitarbeiter gibt.

Dann die zugehörige Versionstabelle. Dadurch wird eine 1-m-Beziehung zur statischen Tabelle hergestellt, da es zu einem Mitarbeiter mehrere Versionen geben kann.

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

In der Versionstabellennotiz gibt es ein Gültigkeitsdatum, aber kein passendes Nicht-mehr-gültig-Feld. Dies liegt daran, dass eine einmal gültige Version gültig bleibt, bis sie durch die nachfolgende Version ersetzt wird. Die Kombination aus ID und EffDate muss eindeutig sein, damit nicht zwei Versionen für denselben Mitarbeiter gleichzeitig aktiv sein können und auch keine Lücke zwischen dem Ende einer Version und dem Start der nächsten Version bestehen kann.

Die meisten Abfragen möchten die aktuelle Version der Mitarbeiterdaten wissen. Diese wird bereitgestellt, indem die statische Zeile für den Mitarbeiter mit der jetzt gültigen Version verknüpft wird. Dies kann mit der folgenden Abfrage gefunden werden:

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;

Dies gibt die einzige Version zurück, die in der jüngsten Vergangenheit begonnen hat. Verwenden der Ungleichung <=in der Datumsprüfung (v2.EffDate <= NOW() ) lässt Wirksamkeitsdaten in der Zukunft zu. Angenommen, Sie wissen, dass ein neuer Mitarbeiter am ersten Tag des nächsten Monats anfängt oder eine Gehaltserhöhung für den 13. des nächsten Monats geplant ist, können diese Daten im Voraus eingefügt werden. Solche "vorinstallierten" Einträge werden ignoriert.

Lassen Sie die Unterabfrage nicht an sich herankommen. Alle Suchfelder sind indiziert, sodass das Ergebnis recht schnell angezeigt wird.

Es gibt viel Flexibilität mit diesem Design. Die obige Abfrage gibt die neuesten Daten aller aktuellen und vergangenen Mitarbeiter zurück. Sie können das TermDate überprüfen Feld, um nur anwesende Mitarbeiter zu erhalten. Da viele Stellen in Ihren Apps nur an den aktuellen Informationen der aktuellen Mitarbeiter interessiert sind, würde diese Abfrage eine gute Ansicht ergeben (das abschließende where weglassen). Klausel). Die Apps müssen nicht einmal wissen, dass solche Versionen existieren.

Wenn Sie ein bestimmtes Datum haben und die Daten sehen möchten, die zu diesem Zeitpunkt gültig waren, ändern Sie das v2.EffDate <= NOW() in der Unterabfrage zu v2.EffDate <= :DateOfInterest .

Weitere Einzelheiten finden Sie in einer Folienpräsentation hier und in einem nicht ganz vollständigen Dokument hier.

Um ein wenig von der Erweiterbarkeit des Designs zu zeigen, beachten Sie, dass es ein IsWorking gibt Kennzeichen in der Versionstabelle sowie ein Beendigungsdatum in der statischen Tabelle. Wenn ein Mitarbeiter das Unternehmen verlässt, wird das letzte Datum in die statische Tabelle eingefügt und eine Kopie der neuesten Version mit IsWorking auf false gesetzt wird in die Versionstabelle eingefügt.

Es ist durchaus üblich, dass Mitarbeiter ein Unternehmen für eine Weile verlassen und dann wieder eingestellt werden. Mit nur dem Datum in der statischen Tabelle kann der Eintrag wieder aktiviert werden, indem Sie dieses Datum einfach auf NULL zurücksetzen. Aber eine "Rückblick"-Abfrage für jeden Zeitpunkt, zu dem die Person kein Angestellter mehr war, würde ein Ergebnis zurückgeben. Es gäbe keinen Hinweis darauf, dass sie das Unternehmen verlassen hätten. Aber eine Version mit IsWorking =false beim Verlassen des Unternehmens und IsWorking =true bei der Rückkehr zum Unternehmen ermöglicht eine Überprüfung dieses Werts zum Zeitpunkt des Interesses und ignoriert Mitarbeiter, wenn sie keine Mitarbeiter mehr waren, selbst wenn sie später zurückgekehrt sind.