在SQL中查找连续增加的数字的最长序列

Pat*_*len 5 sql sql-server

对于这个例子,我说我有一个包含两个字段的表,AREA varchar(30)OrderNumber INT.

该表具有以下数据

AREA      | OrderNumber
Fontana   |       32
Fontana   |       42
Fontana   |       76
Fontana   |       12
Fontana   |        3
Fontana   |       99
RC        |       32
RC        |        1
RC        |        8
RC        |        9
RC        |        4
Run Code Online (Sandbox Code Playgroud)

我想回来

我想要返回的结果是每个区域增加连续值的最长长度.为了Fontana it is 3 (32, 42, 76).For RC it is 2 (8,9)

AREA    | LongestLength
Fontana |          3
RC      |          2
Run Code Online (Sandbox Code Playgroud)

我如何在MS Sql 2005上执行此操作?

And*_*mar 8

一种方法是使用跨越每一行的递归CTE.如果行符合条件(增加相同区域的订单号),则将链长增加1.如果没有,你开始一个新的链:

; with  numbered as
        (
        select  row_number() over (order by area, eventtime) rn
        ,       *
        from    Table1
        )
,       recurse as
        (
        select  rn
        ,       area
        ,       OrderNumber
        ,       1 as ChainLength
        from    numbered
        where   rn = 1
        union all
        select  cur.rn
        ,       cur.area
        ,       cur.OrderNumber
        ,       case
                when cur.area = prev.area 
                     and cur.OrderNumber > prev.OrderNumber 
                     then prev.ChainLength + 1
                else 1
                end
        from    recurse prev
        join    numbered cur
        on      prev.rn + 1 = cur.rn
        )
select  area
,       max(ChainLength)
from    recurse
group by
        area
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle的实例.

另一种方法是使用查询来查找"中断",即结束同一区域的递增顺序号序列的行.中断之间的行数是长度.

; with  numbered as
        (
        select  row_number() over (order by area, eventtime) rn
        ,       *
        from    Table1 t1
        )
        -- Select rows that break an increasing chain
,       breaks as
        (
        select  row_number() over (order by cur.rn) rn2
        ,       cur.rn
        ,       cur.Area
        from    numbered cur
        left join
                numbered prev
        on      cur.rn = prev.rn + 1
        where   cur.OrderNumber <= prev.OrderNumber
                or cur.Area <> prev.Area
                or prev.Area is null
        )
        -- Add a final break after the last row
,       breaks2 as
        (
        select  *
        from    breaks
        union all
        select  count(*) + 1
        ,       max(rn) + 1
        ,       null
        from    breaks
        )
select  series_start.area
,       max(series_end.rn - series_start.rn)
from    breaks2 series_start
join    breaks2 series_end
on      series_end.rn2 = series_start.rn2 + 1
group by
        series_start.area
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle的实例.