新しい従業員がいつ採用または解雇されたかを単純に追跡したい場合は、関連するフィールドを従業員テーブル自体に追加することから始めてください:HireDate date NOT NULL
およびTerminationDate date NULL
.
次に、特定の日の人数 (および詳細) を決定するのは非常に簡単です。
SELECT EmployeeID, EmployeeName, ...
FROM Employees
WHERE HireDate <= @EndDate
AND (TerminationDate IS NULL OR TerminationDate > @BeginDate)
変更(つまり、タイトルの変更)を追跡する必要がある場合、最大の柔軟性を提供するアプローチは、トリガー (またはデータベースの組み込みの変更追跡が利用可能な場合) を使用してリアルタイムの履歴テーブルを維持することです。完全なスナップショットは、アプリの存続期間中に膨大な量のスペースを消費するため、お勧めしません。
履歴テーブルには、ベース テーブルのすべてのフィールドに加えて、変更日とトランザクション タイプの 2 つのフィールドが含まれている必要があります。おそらく 3 番目の autonumber/sequence/identity フィールドも同様です。T-SQL のバージョンは次のとおりです。
CREATE TABLE EmployeeHistory
(
TransactionID int NOT NULL IDENTITY(1, 1)
CONSTRAINT PK_EmployeeHistory PRIMARY KEY CLUSTERED,
TransactionDate datetime NOT NULL,
TransactionType tinyint NOT NULL, -- 1 = Add, 2 = Change, 3 = Delete
EmployeeID int NOT NULL,
EmployeeName varchar(100) NOT NULL,
...
)
次に、トリガーでそれを維持します。
CREATE TRIGGER tr_Employees_History
ON Employees
FOR INSERT, UPDATE
AS BEGIN
INSERT EmployeeHistory (TransactionDate, TransactionType, EmployeeID, ...)
SELECT
GETDATE(),
CASE
WHEN d.EmployeeID IS NULL THEN 1
WHEN (i.TerminationDate IS NOT NULL) AND
(d.TerminationDate IS NULL) THEN 3
ELSE 2
END,
i.EmployeeID, i.EmployeeName, ...
FROM inserted i
LEFT JOIN deleted d
ON d.EmployeeID = i.EmployeeID
END
従業員レコードを削除TerminationDate
せず、単に;を設定すると仮定します。代わりに削除する場合 (これを行わないでください)、 2行DELETE
目の代わりに同様のトリガーを記述する必要があります。CASE WHEN i.TerminationDate ...
次に、履歴テーブルをシードします。
INSERT EmployeeHistory (TransactionDate, TransactionType, EmployeeID, ...)
SELECT HireDate, 1, EmployeeID, ...
FROM Employees
注 - がない場合は、HireDate
それを置き換えてGETDATE()
ください - 履歴は、シードした瞬間からのみ有効になります。
過去の「スナップショット」を取得したい場合は、次のようにします。
CREATE FUNCTION dbo.GetEmployeeSnapshot(@ReportDate datetime)
RETURNS TABLE
AS RETURN
WITH History_CTE AS
(
SELECT
TransactionType, EmployeeID, EmployeeName, ...,
ROW_NUMBER() OVER (ORDER BY TransactionDate DESC) AS RowNum
FROM EmployeeHistory
WHERE TransactionDate <= @ReportDate
)
SELECT *
FROM History_CTE
WHERE RowNum = 1
AND TransactionType IN (1, 2) -- Filter out terminated employees
そして、このクエリの実行速度が遅い場合や、人数などの特定の集計を高速化する必要がある場合は、そのときだけスナップショット テーブルについて考え始める必要があります。
CREATE TABLE HeadcountHistory
(
ReportDate datetime NOT NULL
CONSTRAINT PK_HeadcountHistory PRIMARY KEY CLUSTERED,
HeadCount int NOT NULL
)
そして更新手続き:
CREATE PROCEDURE dbo.UpdateHeadcountHistory
AS
DECLARE @ReportDate datetime
SET @ReportDate = GETDATE()
INSERT HeadcountHistory (HeadCount)
SELECT @ReportDate, COUNT(*)
FROM dbo.GetEmployeeSnapshot(@ReportDate)
スケジュールされたジョブの一部としてその最後の sproc を実行すると、必要な特定の集計の非正規化されたレポート テーブルが作成されます。
これよりも複雑な場合は、代わりにデータ ウェアハウスを検討することをお勧めします。