如果您只是想追蹤新僱員被聘用或終止的情況,那麼您應該先將相關字段添加到僱員表本身:HireDate date NOT NULL
和TerminationDate date NULL
。
然後它真的很容易確定在某一天一個人數(和細節):
SELECT EmployeeID, EmployeeName, ...
FROM Employees
WHERE HireDate <= @EndDate
AND (TerminationDate IS NULL OR TerminationDate > @BeginDate)
如果您需要跟蹤修改(即標題的更改),然後是方法,將爲您提供最大的靈活性是使用觸發器(或數據庫的內置更改跟蹤,如果可用)維護實時歷史記錄表。我不會推薦完整的快照,因爲這會在應用程序的整個生命週期中消耗大量空間。
你的歷史記錄表應包含所有字段的基表,外加兩個多 - 修改日期和交易類型。可能是第三個自動編號/序列/標識字段。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
;如果你刪除(請不要這樣做),那麼你需要寫一個類似的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
)
而且更新PROC:
CREATE PROCEDURE dbo.UpdateHeadcountHistory
AS
DECLARE @ReportDate datetime
SET @ReportDate = GETDATE()
INSERT HeadcountHistory (HeadCount)
SELECT @ReportDate, COUNT(*)
FROM dbo.GetEmployeeSnapshot(@ReportDate)
將最後一個存儲過程作爲計劃作業的一部分運行,然後針對特定聚合需要使用非規格化報告表。
任何比這更復雜的事情,我想你會想開始尋找一個數據倉庫。
什麼平臺?例如,SQL Server 2008具有內置的更改跟蹤。 – Aaronaught 2010-01-23 17:23:18
SQL Server 2005,但如果這是2008年的解決方案,我需要上面的,我會考慮升級 – leora 2010-01-23 17:44:02
我會建議詳細說明數據大小和什麼樣的查詢,你會想要在數據上運行 - 也許這會引發一些頭腦。 – 2010-01-23 17:58:49