4

History在 SQL Server 数据库中有一个表,我需要从不同月份获取信息,例如我有一个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 月份重复,因此查询应该带来以下结果:

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

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

谢谢你。

4

2 回答 2

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记录。DateDate

(注意:如果有多个具有相同Date值的记录,它将选择最有可能具有最小值的记录。如果您想以其他方式打破关系ID,可以在子句中添加一个附加列。)ORDER BY

谢谢

于 2013-08-07T00:03:20.197 回答
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)

在此处输入图像描述

见演示SQLFiddle

于 2013-08-07T10:21:07.087 回答