sql >> データベース >  >> RDS >> Oracle

データベース内の履歴ルックアップ値を最適に管理するにはどうすればよいですか?

    バージョニングと呼ばれる手法がありますが、これは長年使用されていますが、いくつかの理由でほとんど機能しません。ただし、バージョン正規形と呼ばれる同様の手法があり、非常に便利であることがわかりました。 Employeesテーブルを使用した例を次に示します。

    まず、静的テーブルが作成されます。これはメインエンティティテーブルであり、エンティティに関する静的データが含まれています。静的データとは、生年月日など、エンティティの存続期間中に変更されることが予想されないデータです。

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

    このようなテーブルと同様に、従業員ごとに1つのエントリがあることを理解することが重要です。

    次に、関連するバージョンテーブル。これにより、従業員には複数のバージョンが存在する可能性があるため、静的テーブルとの1mの関係が確立されます。

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

    バージョン表の注記には、発効日がありますが、一致する無効になったフィールドはありません。これは、バージョンが有効になると、次のバージョンに置き換えられるまで有効なままになるためです。 IDとEffDateの組み合わせは一意である必要があります。これにより、同じ従業員に対して同時にアクティブな2つのバージョンが存在したり、1つのバージョンが終了してから次のバージョンが開始するまでの間にギャップが生じたりすることはありません。

    ほとんどのクエリは、従業員データの現在のバージョンを知りたいと思うでしょう。これは、従業員の静的行を現在有効なバージョンと結合することによって提供されます。これは、次のクエリで見つけることができます:

    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;
    

    これにより、最新の過去に開始された唯一のバージョンが返されます。日付チェックで不等式<=を使用する(v2.EffDate <= NOW() )将来の発効日を考慮に入れます。新入社員が来月の初日に就職するか、昇給が来月の13日に予定されていることがわかっている場合、このデータを事前に挿入できます。このような「プリロードされた」エントリは無視されます。

    サブクエリを取得させないでください。すべての検索フィールドにインデックスが付けられているため、結果は非常に高速です。

    この設計には多くの柔軟性があります。上記のクエリは、現在および過去のすべての従業員の最新データを返します。 TermDateを確認できます 現在の従業員だけを取得するフィールド。実際、アプリ内の多くの場所は現在の従業員の現在の情報にのみ関心があるため、そのクエリは適切なビューになります(最後のwhereは省略してください)。 句)。アプリがそのようなバージョンが存在することさえ知る必要はありません。

    特定の日付があり、その時点で有効だったデータを確認したい場合は、v2.EffDate <= NOW()を変更します。 v2.EffDate <= :DateOfInterestへのサブクエリで 。

    詳細については、こちらのスライドプレゼンテーションと、まだ完成していないドキュメントをご覧ください。

    デザインの拡張性を少し示すために、IsWorkingがあることに注意してください。 バージョンテーブルのインジケータと静的テーブルの終了日。従業員が会社を辞めると、最終日が静的テーブルに挿入され、IsWorkingを含む最新バージョンのコピーが挿入されます。 falseに設定 バージョンテーブルに挿入されます。

    従業員がしばらく会社を辞めてから再び雇用されることはかなり一般的です。静的テーブルの日付だけで、その日付をNULLに戻すだけで、エントリを再度アクティブ化できます。しかし、その人がもはや従業員ではなくなったときの「振り返り」クエリは、結果を返します。彼らが会社を辞めたという兆候はありません。ただし、IsWorkingを含むバージョン =会社を辞めるときはfalse、IsWorking =会社に戻ったときにtrueになると、関心のあるときにその値を確認でき、後で戻ったとしても、従業員でなくなった従業員は無視されます。



    1. 一貫性のないPostgreSQLスレーブを再構築する方法

    2. MySQLクライアントがMySQLdbと自動再接続できるようにするにはどうすればよいですか?

    3. SQL Serverの置き換え、特定の文字の後のすべてを削除

    4. データベースユーザー権限とは何ですか?