根据日期计算每行创建多行

时间:2017-10-05 21:43:23

标签: sql sql-server

我从来没有做过这样的事情,当我谷歌时无法找到任何指导。如何基于一行数据创建多行

例如,这是我的数据:

Employee | EmploymentDate
1          1/1/2017

每三个月我需要计算一次水平。

Employee | EmploymentDate |  Level | LevelDateRange
1          1/1/2017          1       1/1/2017 - 3/31/2017
1          1/1/2017          2       4/1/2017 - 6/30/2017
1          1/1/2017          3       7/1/2017 - 9/30/2017

LevelDateRange计算:

Start Date: If 1st level then EmploymentDate 
            else previous LevelDateRange end date + 1
End Date: If 1st level then EmployemeentDate + 3 months minus a day 
          else Start date + 3 months

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

在您的情况下,您可以考虑cross apply

select d.employee, v.*
from mydata d cross apply
     (values (1, employmentdate, dateadd(day, -1, dateadd(month, 3, d.employmentdate))),
             (2, dateadd(month, 3, employmentdate), dateadd(day, -1, dateadd(month, 6, d.employmentdate))),
             (3, dateadd(month, 6, employmentdate), dateadd(day, -1, dateadd(month, 9, d.employmentdate)))
     ) v(lev, startdate, enddate);

我建议您将开始日期和结束日期保留在不同的列中。在应用程序级别或查询数据库时将它们组合成一个字符串。

答案 1 :(得分:2)

计数表和CTE:

DECLARE @StartDate DATE
SELECT @StartDate = EmploymentDate FROM emp
DECLARE @MonthsSinceStart INT = DATEDIFF(mm,@startDate,GETDATE())
DECLARE @NumLevels INT = @MonthsSinceStart / 3

--100 row tally table
IF OBJECT_ID('tempdb..#Tally') IS NOT NULL DROP TABLE #Tally
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS Level
INTO #Tally
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n);

WITH cte AS
(
    SELECT  Employee,
            EmploymentDate,
            Level,
            EmploymentDate AS StartDate,
            DATEADD(dd,-1,DATEADD(mm,3,EmploymentDate)) AS EndDate
    FROM    emp
            CROSS JOIN #Tally   
    WHERE   #Tally.Level =1 
    UNION ALL
    SELECT  Employee,
            EmploymentDate,
            Level + 1,
            DATEADD(dd,1,EndDate) AS StartDate,
            DATEADD(dd,-1,DATEADD(mm,3,DATEADD(dd,1,EndDate))) AS EndDate
    FROM    cte
    WHERE   cte.Level < @NumLevels
)
SELECT  Employee,
        EmploymentDate,
        Level,
        CONVERT(NVARCHAR(10),StartDate) + ' - ' + CONVERT(NVARCHAR(10),EndDate)
FROM cte;

建议您在表格中为多个行进行测试