我在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
如何为这些案例构建查询?
谢谢。
答案 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)
请参阅SQLFiddle