È possibile farlo utilizzando LEAD
, LAG
funzioni finestra disponibili da 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
L'idea alla base della query di cui sopra è semplice: per ogni intervallo di [DateStart, DateEnd]
ottenere 'non hanno funzionato' intervallo di destra prima di cio. Se non vi è alcun intervallo che segue l'intervallo corrente, anche il successivo intervallo 'non funzionante' (se presente).
Si noti inoltre che presumo che se DateStart
è NULL
poi DateStart
è anche NULL
per lo stesso ID
.
Demo here
fonte
2015-10-19 21:18:09
Puoi spiegare la logica per risultati come ID record = 3? –
Questo è un problema in SQL Server 2008. È possibile eseguire l'aggiornamento a SQL Server 2012? –
Consideralo fatto. Posso gestirlo nel 2012 se questo aiuta. – Brian