【发布时间】:2013-01-20 02:50:54
【问题描述】:
我正在寻找一种更有效的方法来在 sql server 2008 中实现分页。
我需要检索结果集行@from 到@to,按分值排序,但我还需要检索@from 和@to 之前和之后与那些特定@from 和@ 的分值匹配的所有行到行。例如,这可能类似于以下两个查询之一:
注意,分数值不是唯一的,没有索引,也不会以预先排序的形式提供给查询的其余部分。
a) (实际上,我认为第一个示例不能保证给出我需要的结果,因为我不认为 2 个子查询中的 order by 可以保证产生相同的排序。但是为了了解我希望查询语法做什么,仅考虑此示例中的子查询中的 order-by 是相同的)
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 个惰性假脱机运算符。有没有更有效的语法?
这是当前的实际执行计划:
【问题讨论】:
-
我的目标是看看是否有什么可以做的,它不假设对分数值进行任何索引,对分数值进行任何预排序,或者使用来自先前执行的查询,例如我不知道上次运行查询时的最低分值是多少。
-
理想情况下,窗口函数查询的执行似乎不一定需要假脱机和连接。我想在 SQL Server 2012 中可能会有一个更新的窗口函数语法,它可能只是做同样的事情,比我的 2008 做的要好一点。但我想使用 2008 年开发人员版或企业版中的现有内容。
-
我没有详细查看您的问题,但这是您总是得到的窗口聚合的计划形状。只有一个线轴在计划中出现了 3 次。有关Common Subexpression Spool 的更多详细信息,请点击此处
标签: sql-server-2008 tsql query-optimization paging