Решение этой проблемы требует от вас ее решения по частям. Вот шаги, которые я использовал для этого:
- Определите, когда начинается остров (когда
SomeCondition
ложно)
- Создайте «идентификационный» номер для каждого острова (в пределах каждого
XyzID
), суммируя число IslandBegin
с при рассмотрении записей в AbcID
порядке
- Определите первый и последний
AbcID
в каждой комбинации XyzID
/ IslandNumber
, где SomeCondition
- истина
- Используйте предыдущий шаг в качестве руководства относительно того, что
StartDate
/ EndDate
вы должны получить для каждой записи в наборе результатов
Пример данных:
declare @sample_data table
(
AbcID int
, XyzID int
, StartDate date
, EndDate date
, SomeCondition bit
)
insert into @sample_data
values (1, 1, '2018-01-01', '2018-03-05', 1)
, (2, 1, '2018-04-20', '2018-05-01', 1)
, (3, 1, '2018-05-02', '2018-05-15', 0)
, (4, 1, '2018-06-01', '2018-07-01', 1)
, (5, 1, '2018-08-01', NULL, 1)
, (6, 2, '2018-01-01', '2018-06-30', 1)
, (7, 2, '2018-07-01', '2018-08-31', 0)
Ответ:
Комментарии в коде показывают, какой шаг выполняет каждая часть CTE .
with island_bgn as
(
--Step 1
select d.AbcID
, d.XyzID
, d.StartDate
, d.EndDate
, d.SomeCondition
, case when d.SomeCondition = 0 then 1 else 0 end as IslandBegin
from @sample_data as d
)
, island_nbr as
(
--Step 2
select b.AbcID
, b.XyzID
, b.StartDate
, b.EndDate
, b.SomeCondition
, b.IslandBegin
, sum(b.IslandBegin) over (partition by b.XyzID order by b.AbcID asc) as IslandNumber
from island_bgn as b
)
, prelim as
(
--Step 3
select n.XyzID
, n.IslandNumber
, min(n.AbcID) as AbcIDMin
, max(n.AbcID) as AbcIDMax
from island_nbr as n
where 1=1
and n.SomeCondition = 1
group by n.XyzID
, n.IslandNumber
)
--Step 4
select p.XyzID
, a.StartDate
, b.EndDate
from prelim as p
inner join @sample_data as a on p.AbcIDMin = a.AbcID
inner join @sample_data as b on p.AbcIDMax = b.AbcID
order by p.XyzID
, a.StartDate
, b.EndDate
Результаты:
+-------+------------+------------+
| XyzID | StartDate | EndDate |
+-------+------------+------------+
| 1 | 2018-01-01 | 2018-05-01 |
+-------+------------+------------+
| 1 | 2018-06-01 | NULL |
+-------+------------+------------+
| 2 | 2018-01-01 | 2018-06-30 |
+-------+------------+------------+