Q
используется для получения значения рейтинга rn
, упорядоченного по Column1
.Добавлен в PrimaryKey, если есть связи в Column1
.C
- это рекурсивный CTE, который зацикливается сверху, упорядоченным по rn
с увеличением cc
для каждого возрастающего значения Column2
.Он прервется из рекурсии, когда cc
достигнет 10. Наконец, получите последние 10 строк из C
.Предложение where учитывает случай, когда нет 10 последовательных увеличивающихся значений.
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)
Версия 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)