1

SQL Server 2008 R2でMAS(会計システム)のデータベースをリンクしました。このデータベースで給与レコードが機能する方法は、四半期ごとに給与テーブルのアーカイブが作成され、解雇された従業員が削除された新しい現在の四半期テーブルが作成されることです。一意の従業員IDがあります。構造は、アーカイブバージョンと現在のバージョンで同じです。

したがって、その年の第2四半期では、第1四半期に解雇された従業員は、データベースの第1四半期のコピーにのみ存在します。第1四半期と第2四半期の両方で働いていた従業員は、第1四半期のコピーと第2四半期のコピーにあります。第2四半期に採用された従業員は、第2四半期にのみ発生します。

各従業員の最新のレコードを含むセット(一時テーブル、ビューなど)を作成できる必要があります。このセットは、売上高、職位ごとの平均賃金などのクエリの基礎になります。

UNIONの列を使用してIDのリストをすばやく作成できEmployeeIDますが、他の列は時間の経過とともに変化するため(支払い率、住所など)、UNION一部の従業員が重複するため、すべての列を単純化することはできません。

各従業員の最新の行のみを保持して、履歴データベースをマージするための合理的に効率的な方法はありますか?質問をそのように表現したので、一連のMERGEsを作成し、アーカイブコピーを新しいものから古いものへとステップバックし、一致しない場合は挿入する必要がありますか?もっと良い方法はありますか?

4

1 に答える 1

0

この問題に取り組むにはいくつかの方法があります。これが1つです:

  • テーブルをマージするビューを作成し、それぞれに適切なアーカイブ日付列を追加します
  • EmployeeIDのグループへのビューに対してサブクエリを作成し、MAXアーカイブ日付を取得します
  • サブクエリを使用してビューに参加し、各従業員の最新のレコードを取得します

サンプルテーブルスキーマとテストデータを作成します

    SET NOCOUNT ON

    IF OBJECT_ID('Employee', 'U') IS NOT NULL DROP TABLE Employee;
    GO
    IF OBJECT_ID('Employee2012Q1', 'U') IS NOT NULL DROP TABLE Employee2012Q1;
    GO
    IF OBJECT_ID('Employee2012Q2', 'U') IS NOT NULL DROP TABLE Employee2012Q2;
    GO

    CREATE TABLE dbo.Employee (
        EmployeeID      int IDENTITY(1,1)   NOT NULL    PRIMARY KEY
       ,EmployeeName    varchar(50)         NOT NULL
       ,StartDate       smalldatetime       NOT NULL
       ,EndDate         smalldatetime       NULL
       ,Salary          decimal(18,2)       NOT NULL
       ,Position        varchar(50)         NOT NULL
       ,HomeAddress     varchar(200)        NOT NULL
    )

    -- Employees hired
    INSERT dbo.Employee SELECT 'John Doe', '01/01/2012', NULL, 50000, 'Developer', '12345 Main St, New York, NY'
    INSERT dbo.Employee SELECT 'Jane Doe', '01/01/2012', NULL, 52000, 'Developer', '837 1st St, New York, NY'

    -- Employee fired
    UPDATE A
       SET A.EndDate = '02/01/2012'
      FROM dbo.Employee A
     WHERE A.EmployeeName = 'John Doe'

    -- Table archived
    SELECT * INTO dbo.Employee2012Q1 FROM dbo.Employee

    --  Remove fired employees
    DELETE dbo.Employee WHERE EndDate IS NOT NULL

    -- Employee hired
    INSERT dbo.Employee SELECT 'Jack Flash', '04/01/2012', NULL, 73000, 'Manager', '9580 21st St, New York, NY'

    -- Employee fired
    UPDATE A
       SET A.EndDate = '05/01/2012'
      FROM dbo.Employee A
     WHERE A.EmployeeName = 'Jack Flash'

    -- Table archived
    SELECT * INTO dbo.Employee2012Q2 FROM dbo.Employee

    --  Remove fired employees
    DELETE dbo.Employee WHERE EndDate IS NOT NULL

    SET NOCOUNT OFF
    GO

すべての従業員テーブルをマージするビューを作成します

    IF OBJECT_ID('EmployeeArchive', 'V') IS NOT NULL DROP VIEW dbo.EmployeeArchive
    GO
    CREATE VIEW dbo.EmployeeArchive
    AS
    SELECT CONVERT(smalldatetime, CONVERT(char(10), GETDATE(), 101)) as [ArchiveDate]
          ,EmployeeID
          ,EmployeeName
          ,StartDate
          ,EndDate
          ,Salary
          ,Position
          ,HomeAddress
     FROM dbo.Employee 
    UNION ALL
    SELECT CONVERT(smalldatetime, '03/31/2012') as [ArchiveDate]
          ,EmployeeID
          ,EmployeeName
          ,StartDate
          ,EndDate
          ,Salary
          ,Position
          ,HomeAddress
      FROM dbo.Employee2012Q1 
    UNION ALL
    SELECT CONVERT(smalldatetime, '06/30/2012') as [ArchiveDate]
          ,EmployeeID
          ,EmployeeName
          ,StartDate
          ,EndDate
          ,Salary
          ,Position
          ,HomeAddress
      FROM dbo.Employee2012Q2 
    GO

各従業員の最新情報を入手する

    SELECT A.*
      FROM dbo.EmployeeArchive A
      JOIN (
            SELECT EmployeeID, MAX(ArchiveDate) as MaxArchiveDate
              FROM dbo.EmployeeArchive
             GROUP BY EmployeeID
           ) B
        ON A.EmployeeID  = B.EmployeeID
       AND A.ArchiveDate = B.MaxArchiveDate
于 2013-04-12T05:48:37.250 に答える