从表中获取历史数据

时间:2013-08-06 23:13:25

标签: sql sql-server

我在SQL Server数据库中有一个History表,我需要从不同月份获取信息,例如我有一个EmployeeHistory表,这个表有我记录的任何更新记录为每个员工做。在一个月内我可以有很多更新,但我只有最新的更新。例如,我在一个月内没有做任何更新,我展示了我获得该月的最新更新。

例如

ID Name Email           Date
1  A    a@hotmail.com   2013-01-10
1  A    new@hotmail.com 2013-01-20
1  A    n1@hotmail.com  2013-03-15

在这种情况下,我在2月份没有任何变化,但我需要使用与1月相同的数据,在这种情况下,1月份的最新版本应该在2月重复,因此查询应该带来这样的结果:< / p>

ID Name Email           Date
1  A    new@hotmail.com 2013-01-20
1  A    new@hotmail.com 2013-01-20
1  A    n1@hotmail.com  2013-03-15

如何为这些案例构建查询?

谢谢。

2 个答案:

答案 0 :(得分:1)

首先创建一个表变量,指定您想要查看最新历史记录的月份。

DECLARE @MonthsOfInterest AS TABLE (FirstOfMonth DATE)

接下来,确定要报告的日期。您可以像这样硬编码日期:

INSERT INTO @MonthsOfInterest ( FirstOfMonth ) VALUES('2013-08-01')
INSERT INTO @MonthsOfInterest ( FirstOfMonth ) VALUES('2013-07-01')
INSERT INTO @MonthsOfInterest ( FirstOfMonth ) VALUES('2013-06-01')
...

或者你可能会在过去的12个月内更加温文尔雅并以编程方式加载。

但是一旦你创建并填充了这个表变量,你就会参加比赛。现在这只是一个LEFT JOIN的问题:

SELECT FirstOfMonth, Email, Date
FROM @MonthsOfInterest
    LEFT JOIN HistoryTable ON
        HistoryTable.ID = (
            SELECT TOP 1 ID 
            FROM HistoryTable 
            WHERE Date < @MonthsOfInterest.FirstOfMonth 
            ORDER BY Date DESC
        )

在英语中,对于@MonthsOfInterest中的每条记录,我们加入HistoryTable记录,其Date值小于月初最大的Date值。

(注意:如果有多个具有相同Date值的记录,则会选择最有可能ID值最小的记录。您可以向{{1}添加其他列如果你想以其他方式打破关系,请使用子句。)

由于

答案 1 :(得分:1)

要创建月份序列,您可以使用系统表master..spt_values或您自己的序列表。因此,您可以找到所有月份的值,无论是否有更改

SELECT DATENAME(mm, DATEADD(mm, v.number-1, '20010101')) AS mName, 
       o.Id, o.Email, o.[Date]
FROM master..spt_values v
  OUTER APPLY(
              SELECT h3.Id, h3.NAME, h3.Email, h3.Date 
              FROM (
                    SELECT h.Id, MAX(h.[Date]) AS [Date]
                    FROM dbo.EmployeeHistory h
                    WHERE MONTH(h.[Date]) <= v.number
                    GROUP BY h.Id
                    ) h2 JOIN dbo.EmployeeHistory h3
                      ON h2.Id = h3.Id AND h2.Date = h3.Date
              ) o
WHERE v.[type] = 'P' AND v.number BETWEEN 1 AND 12

为了获得更好的性能,您可以使用以下索引:

CREATE INDEX x ON dbo.EmployeeHistory(Id, [Date]) INCLUDE(Name, Email)

enter image description here

请参阅SQLFiddle

上的演示