我正在寻找一种更有效的方法来在sql server 2008中实现我的分页。
我需要检索结果集行@from到@to,按分数值排序,但我还需要检索@from和@to之前和之后的所有行,这些行匹配那些特定的@from和@的得分值到行。例如,这可能是以下两个查询中的任何一个:
N.b.,得分值不是唯一的,没有编入索引,也不会以预先排序的形式提供给查询的其余部分。
a)(实际上,我认为第一个例子不能保证给出我需要的结果,因为我不认为2个子查询中的顺序可以保证产生相同的顺序。但是为了这个缘故理解我想要查询语法的内容,只考虑这个例子,子查询中的顺序是相同的)
select *
from (
select top (@to) * with ties
from result_set
order by score desc
) tt
union
select
from (
select top (@to - @from + 1) * with ties
from (
select top (@to) *
result_set
order by score desc
) tt
order by score asc
) tt
order by score desc
或
b)中
/*EDIT: nested the rank() window function and related where criteria one level deeper than
the count(*), as this gave me significant (25%) decrease in runtime with my data, and just
kinda makes sense.*/
select score
from (
select
score,
myrank,
count(*) over (partition by score) frequency
from (
select
score,
rank() over (order by score desc) myrank
from result_set
) tt
where myrank <= @to
) tt
where @from <= myrank + frequency - 1
order by score desc
我使用语法(b)结合以下测试CTE得到我需要的结果:
with result_set (score) as (
select 0.5 union all
select 0.5 union all
select 0.2 union all
select 0.1 union all
select 0.55 union all
select 0.5 union all
select 0.1
)
但是分区窗口函数需要2个嵌套循环和3个惰性假脱机操作符。是否有更有效的语法?
以下是当前的实际执行计划:
答案 0 :(得分:0)
您可以先获得最低价值。然后使用顶部关系定期分页,但包括值等于底部值:
DECLARE @pageSize int = @to - @from + 1
DECLARE @bottomValue <datatype> =
(
SELECT MIN(score)
FROM
(
SELECT TOP(@from) score
FROM <TABLENAME>
ORDER BY score DESC
)
)
SET @from = @from - 1
SELECT TOP (@pageSize) * WITH TIES --TopTies
FROM <TABLENAME>
WHERE <COLUMN_ID> NOT IN
(
SELECT TOP (@from) <COLUMN_ID>
FROM <TABLENAME>
ORDER BY score DESC
)
ORDER BY score DESC
UNION
SELECT *
FROM <TABLENAME>
WHERE score = @bottomValue --BottomTies
使用此查询的好处是,对于第一页,您将获得更快的响应时间(更少的读取)。缺点是随着@from的增加,读数也会增加。但是,我认为如果使用row_number或rank等函数,则无论是第一页还是最后一页,都必须评估所有表数据。
另一种方式,不确定最适合你的情况,是将最后一个值发送到sp:
--Parameter
@lastScore <datatype> = null
--Logic
SELECT TOP(@to) * WITH TIES
FROM [TABLENAME]
WHERE score < @lastScore OR @lastScore IS NULL -- opt1
--WHERE score <= @lastScore OR @lastScore IS NULL opt2
ORDER BY score DESC