首页 文章

创建没有光标的ID范围

提问于
浏览
0

不确定是否已经问过这个或类似的问题,但我找不到 .

要求在不更改值时创建ID范围 . 可以使用此架构:

declare @mytable as table(ID int, Val int)

insert into @mytable values
(1,     1),
(2,     1),
(3,     1),
(4,     2),
(5,     2),
(6,     2),
(7,     2),
(8,     1),
(9,     1),
(10,    1),
(11,    4),
(12,    4),
(13,    4),
(14,    4),
(15,    4),
(16,    5);

预期的结果将是

StartID     EndID   Val
1           3       1
4           7       2
8           10      1
11          15      4
16          16      5

现在我可以通过运行游标来实现这一点 . 如果n情况下记录的数量将是数百万,我认为,光标会更慢 . 我希望它可以使用一些复合查询编写,但无法弄清楚如何 .

所以我在编写那种查询时需要帮助,不用提及,它是 not 一个学校/拼贴项目/作业 .

2 回答

  • 0

    这是一个空白和岛屿问题 . 但最简单的方法是行号的不同:

    select min(id) as startId, max(id) as endId, val
    from (select t.*,
                 row_number() over (order by id) as seqnum,
                 row_number() over (partition by val order by id) as seqnum_v
          from @mytable t
         ) t
    group by (seqnum - seqnum_v), val
    order by startId;
    
  • 2

    这是一个gaps-and-islands场景,您尝试根据 Val 中的更改将记录组合在一起 .

    这是使用window functions来确定 Val 何时更改,并分配 island_nbr .

    Answer:

    select min(b.ID) as StartID
    , max(b.ID) as EndID
    , max(b.Val) as Val
    from (
        select a.ID
        , a.Val
        , sum(a.is_chng_flg) over (order by a.ID asc) as island_nbr
        from (
            select m.ID
            , m.Val
            , case lag(m.Val, 1, m.Val) over (order by m.ID asc) when m.Val then 0 else 1 end is_chng_flg
            from @mytable as m
            ) as a
        ) as b
    group by b.island_nbr --forces the right records to show up
    order by 1
    

相关问题