我有下表:
|id|sog|zoneId|
| 1| 20| 2|
| 2| 2| 2|
| 3| 10| 2|
| 4| 10| 1|
| 5| 3| 1|
| 6| 8 | 2|
| 7| 1 | 2|
| 8| 3 | 2|
| 9| 4 | 2|
行按id
列排序。
我想提出一个要返回的查询:
|id|sog|zoneId|grpId|
| 1| 20| 2| 1|
| 2| 2| 2| 1|
| 3| 10| 2| 1|
| 4| 10| 1| 2|
| 5| 3| 1| 2|
| 6| 8 | 2| 3|
| 7| 1 | 2| 3|
| 8| 3 | 2| 3|
| 9| 4 | 2| 3|
答案 0 :(得分:2)
以下是基于Itzik Ben-Gan's solution to islands and gaps的解决方案:
;with q as (
select *,
row_number() over (order by id)
- row_number() over (order by zoneid, id) as grp
from thetable
)
select id, sog, zoneid,
min (id) over(partition by zoneid, grp) as grp
from q
order by id
Grp
与两个序列保持一致,id
和ZoneID, id
一起运行,但这些数字既不是有序的也不是连续的。通过每组取min(id)简单地构造有序组号。如果您需要顺序组号,请添加另一个检索dense_rank() over(order by grp)
的cte。
Sql Fiddle this way。 (感谢w0lf)。
答案 1 :(得分:1)
如果你的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
如果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
但我不确定性能是否适合