Expand "From" & "To" date columns to 1 row per day within that range
取以下样本数据:
1 2 3 4 5 6 7 8 9 10 | WITH SampleData AS ( SELECT '8000213' AS EmployeeID, '2014-08-25 00:00:00.000' AS StartDate, '2014-08-31 00:00:00.000' AS EndDate, 28.5 AS HPW UNION ALL SELECT '8000213' AS EmployeeID, '2014-10-01 00:00:00.000' AS StartDate, NULL AS EndDate, 33 AS HPW UNION ALL SELECT '0003289' AS EmployeeID, '2014-04-25 00:00:00.0000' AS StartDate, '2014-04-30 00:00:00.000' AS EndDate, 36 AS HPW UNION ALL SELECT '0003289' AS EmployeeID, '2014-05-01 00:00:00.000' AS StartDate, NULL AS EndDate, 20 AS HPW ) SELECT * FROM SampleData |
我们如何扩展这个数据如下(当没有结束日期时,假设当前日期):
我怀疑这里需要某种递归/CTE/计数表,但我无法理解它!
制作日期生成器的方法有很多种;整篇文章都专门讨论了哪一篇最快,但为了简单起见,我将调整此处找到的那一篇。我建议对该主题进行一些阅读,并在数据库中保留一个真实的日期表,您可以将其用于此类查询(而不是为您执行的每个查询即时生成一个)。
第一步:创建日期表
第二步:将表中的每个日期连接到员工(注意:我也在过滤这个以仅显示大于 SampleData 中最小开始日期的日期)
第三步:将日期/不同员工加入您的数据,以检索到给定日期有效的 HPW。
SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | DECLARE @StartDate DATETIME = '2014-01-01 00:00:00.000'; -- this can be any date below the minimum StartDate WITH SampleData AS ( SELECT '8000213' AS EmployeeID, '2014-08-25 00:00:00.000' AS StartDate, '2014-08-31 00:00:00.000' AS EndDate, 28.5 AS HPW UNION ALL SELECT '8000213' AS EmployeeID, '2014-10-01 00:00:00.000' AS StartDate, NULL AS EndDate, 33 AS HPW UNION ALL SELECT '0003289' AS EmployeeID, '2014-04-25 00:00:00.000' AS StartDate, '2014-04-30 00:00:00.000' AS EndDate, 36 AS HPW UNION ALL SELECT '0003289' AS EmployeeID, '2014-05-01 00:00:00.000' AS StartDate, NULL AS EndDate, 20 AS HPW ), SampleDateTable AS ( SELECT @StartDate AS myDate UNION ALL SELECT DATEADD(DAY,1,myDate) FROM SampleDateTable WHERE DATEADD(DAY,1,myDate) <= GETDATE() ) SELECT EachEmployee.EmployeeID, a.myDate, SampleData.HPW FROM SampleDateTable a INNER JOIN ( SELECT EmployeeID, MIN(StartDate) MinStartDate FROM SampleData GROUP BY EmployeeID ) EachEmployee ON a.MyDate >= EachEmployee.MinStartDate LEFT JOIN SampleData ON EachEmployee.EmployeeID = SampleData.EmployeeID AND a.myDate >= SampleData.StartDate AND a.myDate <= ISNULL(SampleData.EndDate, GETDATE()) ORDER BY EachEmployee.EmployeeID DESC, a.MyDate OPTION (MAXRECURSION 0) |
或者,您可以简单地继续 CTE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | --Replace the enddate with"Getdate()" if you require expansion until"today/current" DECLARE @DefaultEnddate Datetime = '2014-10-15 00:00:00.000' ;WITH SampleData AS ( SELECT '8000213' AS EmployeeID, '2014-08-25 00:00:00.000' AS StartDate, '2014-08-31 00:00:00.000' AS EndDate, 28.5 AS HPW UNION ALL SELECT '8000213' AS EmployeeID, '2014-10-01 00:00:00.000' AS StartDate, NULL AS EndDate, 33 AS HPW UNION ALL SELECT '0003289' AS EmployeeID, '2014-04-25 00:00:00.000' AS StartDate, '2014-04-30 00:00:00.000' AS EndDate, 36 AS HPW UNION ALL SELECT '0003289' AS EmployeeID, '2014-05-01 00:00:00.000' AS StartDate, NULL AS EndDate, 20 AS HPW ) , Base AS ( SELECT EmployeeID, StartDate = CONVERT(datetime, StartDate) , EndDate = CONVERT(datetime,isnull(EndDate,@DefaultEnddate)), HPW FROM SampleData) , Expanded AS (SELECT EmployeeID, StartDate AS [DATE], HPW , EndDate FROM Base UNION ALL SELECT EmployeeID, [DATE] = [DATE] + 1, HPW , EndDate FROM Expanded WHERE [DATE] < EndDate ) SELECT EmployeeID,[DATE], HPW FROM Expanded ORDER BY EmployeeID, [DATE] OPTION (MAXRECURSION 1000) |