Database design 对数据库数据进行历史比较的最佳方法是什么?

Database design 对数据库数据进行历史比较的最佳方法是什么?,database-design,tracking,Database Design,Tracking,我有一个数据库,里面有一个组织的员工名单。有一个主employee表和多个联接表 我希望开始跟踪此数据的每周和每月指标,以便我可以执行以下操作: 3月1日:员工人数100人(2月增加1-2人) 4月1日:员工人数101人(3月增加3-2人) 5月1日:员工人数105人(4月增加10人-6人) 我正在努力寻找最好的方法来做这件事。我是否: 在每个月的第一天拍摄完整的数据库快照,让我的应用程序查询多个数据库以生成这些报告 尝试跟踪某些db触发的历史记录表中的所有更改,并尝试聚合这些信息以尝试建立每个

我有一个数据库,里面有一个组织的员工名单。有一个主employee表和多个联接表

我希望开始跟踪此数据的每周和每月指标,以便我可以执行以下操作:

3月1日:员工人数100人(2月增加1-2人)
4月1日:员工人数101人(3月增加3-2人)
5月1日:员工人数105人(4月增加10人-6人)

我正在努力寻找最好的方法来做这件事。我是否:

  • 在每个月的第一天拍摄完整的数据库快照,让我的应用程序查询多个数据库以生成这些报告

  • 尝试跟踪某些db触发的历史记录表中的所有更改,并尝试聚合这些信息以尝试建立每个月的当前状态

  • 还有其他建议吗


  • 如果您只是在计划中运行这个,那么我将创建一个数据汇总表。。。每月运行一次进程进行计数,并在汇总表中添加一行表示数据。这样,您就可以回顾历史并生成所需的任何统计数据。您可能想考虑以比您计划报告的频率更频繁地生成这些数据(例如,每周)。只要您的分辨率高于报告期,您就应该拥有所需的所有数据。

    如果您只是想跟踪新员工的雇用或终止时间,那么您应该首先向员工表本身添加相关字段:
    HireDate date NOT NULL
    TerminationDate NULL

    然后,在任何一天确定员工人数(以及详细信息)都非常容易:

    SELECT EmployeeID, EmployeeName, ...
    FROM Employees
    WHERE HireDate <= @EndDate
    AND (TerminationDate IS NULL OR TerminationDate > @BeginDate)
    
    然后用触发器保持:

    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
    
    我假设您不删除员工记录,只设置一个
    终止日期
    ;如果改为删除(请不要这样做),则需要编写类似的
    delete
    触发器,而不是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 PROCEDURE dbo.UpdateHeadcountHistory
    AS
    
    DECLARE @ReportDate datetime
    SET @ReportDate = GETDATE()
    
    INSERT HeadcountHistory (HeadCount)
        SELECT @ReportDate, COUNT(*)
        FROM dbo.GetEmployeeSnapshot(@ReportDate)
    
    将最后一个存储过程作为计划作业的一部分运行,然后您将获得所需特定聚合的非规范化报告表


    任何比这更复杂的事情,我想你应该开始研究数据仓库。

    但是如果我想深入查看历史日期的详细信息,我怎么能“返回”呢如果您想知道历史日期的详细信息,那么除了将相应的列复制到另一个表中之外,您没有其他选择。这将是一个相当不寻常的要求,我想问你为什么需要这样的历史知识水平??什么平台?例如,SQL Server 2008具有内置的更改跟踪.SQLServer 2005,但是如果这是一个2008的解决方案,那么我将考虑升级,我建议详细说明数据大小和您希望在数据上运行什么样的查询,这可能会引发一些想法。
    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)