Puisque c'est la question initiale - je poste la réponse ici. Je suggérerais d'abandonner vos boucles tous ensemble. Voici un moyen avec 2 boucles CTE et ZERO.
declare @table table (ID int, StartDate date, EndDate date)
Insert Into @table
(
ID
, StartDate
, EndDate
)
Values
(1, '2017-01-01', '2017-02-01'),
(1, '2017-01-09', '2017-01-28'),
(1, '2017-04-01', '2017-04-30'),
(1, '2017-04-05', '2017-05-20'),
(1, '2017-04-20', '2017-06-12'),
(2, '2017-06-02', '2017-06-20'),
(2, '2017-06-14', '2017-07-31'),
(2, '2017-06-14', '2017-07-31'),
(2, '2017-06-19', '2017-07-31'),
(2, '2017-06-19', '2017-07-31')
;with cte as(
select
t1.ID
,t1.StartDate
,t1.EndDate
,DT = (select min(StartDate) from @table t2 where t2.StartDate > DATEADD(day,30,t1.StartDate))
from
@table t1),
cte2 as(
select
ID
,StartDate
,EndDate
,dense_rank() over (order by isnull(DT,(select max(StartDate) from cte))) as Flag
from
cte)
select
ID
,StartDate
,EndDate
,case when Flag % 2 = 0 then 2 else Flag % 2 end as Flag
from cte2