あなたのIDがシーケンシャルでギャップがない場合、最速の方法は次のようになると思います:
;with cte as (
select
T.id, T.sog, T.zoneId,
1 as grpId
from Table1 as T
where T.id = 1
union all
select
T.id, T.sog, T.zoneId,
c.grpId + case when T.zoneId = c.zoneId then 0 else 1 end as grpId
from cte as c
inner join Table1 as T on T.id = c.id + 1
)
select c.id, c.sog, c.zoneId, c.grpId
from cte as c
SQL フィドルのデモ
Id が連続していないか、ギャップがある場合は、次のことができます。
;with cte1 as (
select
T.id, T.sog, T.zoneId,
row_number() over (order by T.id) as row_num
from Table1 as T
), cte2 as (
select
T.id, T.sog, T.zoneId, T.row_num,
1 as grpId
from cte1 as T
where T.row_num = 1
union all
select
T.id, T.sog, T.zoneId, T.row_num,
c.grpId + case when T.zoneId = c.zoneId then 0 else 1 end as grpId
from cte2 as c
inner join cte1 as T on T.row_num = c.row_num + 1
)
select c.id, c.sog, c.zoneId, c.grpId
from cte2 as c
SQL フィドルのデモ
しかし、パフォーマンスがそのために良いかどうかはわかりません