2010-01-21 56 views
4

我有一個數據庫,有一個組織的僱員名單。有一個主要員工表和連接表的數量。對數據庫數據進行歷史比較的最佳方法是什麼?

我要開始超過一週,一個月一個月的指標跟蹤一週這一數據,所以我可以做這樣的事情:

3月1日:人數100(+1,-2月)
4月1日:人數101(+3,-2年3月)
5月1日:人數105(+10,-6年4月)

我試圖要做到這一點的最好辦法的事。做我:

  1. 以一個完整的數據庫快照在每個月的第一天,並有我的應用程序查詢多個數據庫來生成這些報告。

  2. 儘量保持一些數據庫中的所有變化軌跡觸發歷史表,並嘗試聚合這些信息來試圖建立每月的當前狀態。

  3. 任何其他建議?

+0

什麼平臺?例如,SQL Server 2008具有內置的更改跟蹤。 – Aaronaught 2010-01-23 17:23:18

+0

SQL Server 2005,但如果這是2008年的解決方案,我需要上面的,我會考慮升級 – leora 2010-01-23 17:44:02

+0

我會建議詳細說明數據大小和什麼樣的查詢,你會想要在數據上運行 - 也許這會引發一些頭腦。 – 2010-01-23 17:58:49

回答

2

如果您只是想追蹤新僱員被聘用或終止的情況,那麼您應該先將相關字段添加到僱員表本身:HireDate date NOT NULLTerminationDate 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) 

將最後一個存儲過程作爲計劃作業的一部分運行,然後針對特定聚合需要使用非規格化報告表。

任何比這更復雜的事情,我想你會想開始尋找一個數據倉庫。

1

如果你是剛剛運行此按計劃,那麼我會建立一個數據彙總表...每月一次運行一個程序做你的計數,並添加一行彙總表表示數據。這樣,您可以回顧歷史並生成您需要的任何統計數據。你可能要考慮比您計劃報告(比如,每週)更頻繁的基礎上產生這個數據..只要你有比你應該有你需要的所有數據,報告期內更高的分辨率。

+0

但如果我想深入瞭解歷史日期的詳細信息,那麼我怎麼能「回去」並獲得當時的狀態呢? – leora 2010-01-21 04:58:54

+1

如果您想知道歷史日期的詳細信息,那麼除了將適當的列複製到另一個表中之外,您沒有其他選擇。這將是一個相當不尋常的要求,我會質疑爲什麼你需要這樣的歷史知識水平? – 2010-01-21 05:00:41

相關問題