展开“来自”& “要”在该范围内将列日期定为每天1行

时间:2014-11-13 13:48:54

标签: sql sql-server-2008 tsql common-table-expression

采取以下样本数据:

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

我们如何扩展这些数据如下(当没有结束日期时,假设当前日期):

enter image description here

我怀疑这里需要某种递归/ CTE /计数表,但我不能完全理解它!

2 个答案:

答案 0 :(得分:1)

制作日期生成器的方法有很多种;整篇文章都致力于哪一个是最快的,但为了简单起见,我将调整发现的here。我建议您对该主题进行一些阅读,并在数据库中保存一个真实的日期表,您可以将其用于此类查询(而不是为您执行的每个查询动态生成一个)。

第一步:创建日期表

第二步:将表格中的每个日期加入员工(注意:我也将其过滤为仅显示大于SampleData中最小开始日期的日期)

第三步:将日期/不同员工加入您的数据,以检索截至指定日期的有效HPW。

SQL:

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)

答案 1 :(得分:0)

或者你可以继续CTE:

--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)