我可以在不使用 ROW_NUM () OVER (ORDER BY xxxxx) 的情况下在 Sql Server 中对查询进行分页吗?

Posted

技术标签:

【中文标题】我可以在不使用 ROW_NUM () OVER (ORDER BY xxxxx) 的情况下在 Sql Server 中对查询进行分页吗?【英文标题】:Can I paginate a query in Sql Server without using ROW_NUM () OVER (ORDER BY xxxxx)? 【发布时间】:2012-01-25 04:08:08 【问题描述】:

我正在开发自定义 DAL,现在正在处理自动结果分页。 DAL 根据我们的模型生成动态查询,例如:

Model.All() --> generates "select * from mytable"
Model.Filter ("d=@0", "arg0value") --> generates "select * from mytable where d=@0"
...

我不想为我们的过滤函数添加额外的参数,也不想为分页添加专门的函数(当然,如果可以避免的话)。相反,我想对结果进行分页更改查询之前它被执行。比如……

var resultset = Model.Filter ("d=@0, "arg0value"); // "select * from mytable where d=@0"
resulset = resultset.Paginate (1, 25); // this should paginate the query before loading any objects

在 Oracle 中,使用 ROWNUM 伪列并包装旧查询很容易。

select * from (my old sql) where rownum between 20 and 40

在 Sql Server (2005) 中没有像 ROWNUM 这样的东西。我已经看到有 ROW_NUMBER 函数,但它需要知道查询的内部,因为您需要传递“OVER (ORDER BY xxxx)”子句。

select row_number() over (order By <?????>) as rownum, dv.* from (my old sql) as dv where rownum between 20 and 40

那么,有没有一种方法可以在 Sql Server 中执行此操作,而无需向我们的模型添加特定的参数/函数?

谢谢!

编辑

正如@Dems 所说,我可以解析查询并根据输出字段添加 ORDER BY,但是:首先,我不想要解析的开销,其次,如果查询的类型为“select * ",我无法提取字段。

【问题讨论】:

在 SQL Server 2012 中,将有 OFFSET and FETCH NEXT - 但在那之前,带有 ROW_NUMBER() 的 CTE 是您唯一真正可行的选择... 【参考方案1】:

如果您正在编写自己的数据访问层,并且您想应用 ROW_NUMBER() 只知道查询的输出字段名称(而不是它的内部)...

SELECT
  *
FROM
(
  SELECT
    ROW_NUMBER() OVER (ORDER BY field1, field2, field3) AS row_id,
    *
  FROM
  (
    <your-query>
  )
    AS unordered_data
)
  AS ordered_data
WHERE
  row_id BETWEEN x AND y

【讨论】:

感谢您的回答,但如果上一个查询是“select * ...”,我无法提取字段。我已更新问题以反映这一点。 那么您唯一可用的选项是控制在您的客户端中提取的记录,可能使用记录集。这可用于避免拉取不必要记录的网络流量,但不会为您的 SQL Server 节省任何负载。 看来我必须添加一些特定的功能,这样我才能在查询生成期间使用模型元数据。我等会儿。如果没有更好的答案,我会接受这个,因为有见地。谢谢。

以上是关于我可以在不使用 ROW_NUM () OVER (ORDER BY xxxxx) 的情况下在 Sql Server 中对查询进行分页吗?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle分析函数

带有 Row_Num 的 CASE

从 ROW_NUM 中仅选择编号最大的行以获取最新更新

SQL Server 可以在不使用 cte 的情况下根据排名限制查询结果吗?

Oracle:row_number()rank()dense_rank()

EXCEL中INDEX怎么使用