假设我有以下非常简单的架构:
Create Table MyTable (
PrimaryKey int,
Column1 datetime.
Column2 int
)
Run Code Online (Sandbox Code Playgroud)
我需要一个基于Column1对数据进行排序的查询,并查找前10行,其中当前行中Column2的值大于前一行中column2的值.
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)
| 归档时间: |
|
| 查看次数: |
927 次 |
| 最近记录: |