我从来没有做过这样的事情,当我谷歌时无法找到任何指导。如何基于一行数据创建多行
例如,这是我的数据:
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
有什么建议吗?
答案 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;
建议您在表格中为多个行进行测试