可以使用LEAD
做到这一点,LAG
可以从SQL Server 2012+窗口功能:
;WITH CTE AS (
SELECT ID,
LAG(DateEnd) OVER (PARTITION BY ID ORDER BY DateEnd) AS PrevEnd,
DateStart,
DateEnd,
LEAD(DateStart) OVER (PARTITION BY ID ORDER BY DateEnd) AS NextStart
FROM DatesTable
)
SELECT ID, DateStart, DateEnd
FROM (
-- Get interval right before current [DateStart, DateEnd] interval
SELECT ID,
CASE
WHEN DateStart IS NULL THEN '20150101'
WHEN DateStart > start THEN start
ELSE NULL
END AS DateStart,
CASE
WHEN DateStart IS NULL THEN '20151231'
WHEN DateStart > start THEN DATEADD(d, -1, DateStart)
ELSE NULL
END AS DateEnd
FROM CTE
CROSS APPLY (SELECT COALESCE(DATEADD(d, 1, PrevEnd), '20150101')) x(start)
-- If there is no next interval then get interval right after current
-- [DateStart, DateEnd] interval (up-to end of year)
UNION ALL
SELECT ID, DATEADD(d, 1, DateEnd) AS DateStart, '20151231' AS DateEnd
FROM CTE
WHERE DateStart IS NOT NULl -- Do not re-examine [Null, Null] interval
AND NextStart IS NULL -- There is no next [DateStart, DateEnd] interval
AND DateEnd < '20151231' -- Current [DateStart, DateEnd] interval
-- does not terminate on 31/12/2015
) AS t
WHERE t.DateStart IS NOT NULL
ORDER BY ID, DateStart
上面的查询背后的想法很简单:每[DateStart, DateEnd]
间隔获得“没有工作”区间权在它之前。如果在当前时间间隔之后没有间隔,那么也会得到连续的'未工作'间隔(如果有的话)。
另外请注意,我认为如果DateStart
是NULL
然后DateStart
也NULL
为同一ID
。
Demo here
你能解释一下结果的逻辑吗,比如记录ID = 3吗? –
这是SQL Server 2008中的一个痛点。你可以升级到SQL Server 2012吗? –
考虑完成。如果有帮助,我可以在2012年运行。 – Brian