用于查找连续增加值的T-SQL

Hos*_*146 4 sql-server-2008

假设我有以下非常简单的架构:

Create Table MyTable (
   PrimaryKey int,
   Column1 datetime.
   Column2 int
)
Run Code Online (Sandbox Code Playgroud)

我需要一个基于Column1对数据进行排序的查询,并查找前10行,其中当前行中Column2的值大于前一行中column2的值.

Mik*_*son 5

Q用于获取评级值rn由有序Column1.如果存在关联,则在PrimaryKey中添加Column1.C是一个递归CTE,从顶部开始循环,通过rn递增cc每个增加的值Column2.当它cc达到10 时,它将从递归中断.最后得到最后10行C.当没有10个连续的增加值时,where子句负责处理这种情况.

with Q as
(
  select PrimaryKey,
         Column1,
         Column2,
         row_number() over(order by Column1, PrimaryKey) as rn
  from MyTable
),
C as
(
  select PrimaryKey,
         Column1,
         Column2,
         rn,
         1 as cc
  from Q
  where rn = 1
  union all
  select Q.PrimaryKey,
         Q.Column1,
         Q.Column2,
         Q.rn,
         case 
           when Q.Column2 > C.Column2 then C.cc + 1
           else 1
         end  
  from Q
    inner join C
      on Q.rn - 1 = C.rn
  where C.cc < 10     
)
select top 10 *
from C
where 10 in (select cc from C)
order by rn desc
option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)

版本2 正如Martin Smith在评论中指出的那样,上面的查询确实表现不佳.罪魁祸首是第一个CTE.下面的版本使用表变量来保存排名的行.该primary key指令rn创建一个索引,该索引将在查询的递归部分中的连接中使用.除了表变量之外,这与上面的相同.

declare @T table
(
   PrimaryKey int,
   Column1 datetime,
   Column2 int,
   rn int primary key
);

insert into @T
select PrimaryKey,
       Column1,
       Column2,
       row_number() over(order by Column1, PrimaryKey) as rn
from MyTable;

with C as
(
  select PrimaryKey,
         Column1,
         Column2,
         rn,
         1 as cc
  from @T
  where rn = 1
  union all
  select T.PrimaryKey,
         T.Column1,
         T.Column2,
         T.rn,
         case 
           when T.Column2 > C.Column2 then C.cc + 1
           else 1
         end  
  from @T as T
    inner join C
      on T.rn = C.rn + 1
  where C.cc < 10     
)
select top 10 *
from C
where 10 in (select cc from C)
order by rn desc
option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)