Это решение для алгоритмов, известных как острова и пробелы.
;WITH [Islands] AS
(
SELECT 'A' AS [Name], 0 AS [Value], CAST('2019-10-24' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 0 AS [Value], CAST('2019-10-25' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 0 AS [Value], CAST('2019-10-26' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 1 AS [Value], CAST('2019-10-27' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 1 AS [Value], CAST('2019-10-28' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 1 AS [Value], CAST('2019-10-29' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 0 AS [Value], CAST('2019-10-30' AS DATE) AS [Date] UNION
SELECT 'A' AS [Name], 0 AS [Value], CAST('2019-10-31' AS DATE) AS [Date]
)
, [IslandGroups] AS
(
SELECT
*
,DATEDIFF(DAY, '1900-01-01', [Date]) AS [DifferenceInDays]
,ROW_NUMBER() OVER (ORDER BY [Name], [Value]) AS [RowNumber]
,DATEDIFF(DAY, '1900-01-01', [Date]) - ROW_NUMBER() OVER (ORDER BY [Name], [Value]) AS [IslandGroup]
FROM
[Islands]
)
SELECT
[Name]
,[Value]
,MIN([Date]) AS [starting_date]
,MAX([Date]) AS [starting_date]
FROM
[IslandGroups]
GROUP BY
[Name]
,[Value]
,[IslandGroup]
ORDER BY
[Name]
,MIN([Date])
Вот как это работает. Алгоритм работает путем вычитания функции ранжирования, в данном случае ROW_NUMBER () из разницы в днях между двумя датами. Если вы запустите это, вы увидите, что столбец RowNumber увеличивается, как и DifferenceInDays.
... removed for brevity
, [IslandGroups] AS
(
SELECT
*
,DATEDIFF(DAY, '1900-01-01', [Date]) AS [DifferenceInDays]
,ROW_NUMBER() OVER (ORDER BY [Name], [Value]) AS [RowNumber]
,DATEDIFF(DAY, '1900-01-01', [Date]) - ROW_NUMBER() OVER (ORDER BY [Name], [Value]) AS [IslandGroup]
FROM
[Islands]
)
SELECT
*
FROM
[IslandGroups]
В результате:
A 0 2019-10-24 43760 1 43759 <- First in the series
A 0 2019-10-25 43761 2 43759
A 0 2019-10-26 43762 3 43759
A 0 2019-10-30 43766 4 43762 <- Next set
A 0 2019-10-31 43767 5 43762
A 1 2019-10-27 43763 6 43757 <- Next set
A 1 2019-10-28 43764 7 43757
A 1 2019-10-29 43765 8 43757
Затем вы можете GROUP BY общей группировки островов иполучить MIN () и MAX () [Date] из одной группы.