SQL Server - 没有Order By子句的分页

[英]SQL Server - Pagination Without Order By Clause


My situation is that a SQL statement which is not predictable, is given to the program and I need to do pagination on top of it. The final SQL statement would be similar to the following one:

我的情况是,一个不可预测的SQL语句被赋予程序,我需要在它上面进行分页。最终的SQL语句类似于以下语句:

SELECT * FROM (*Given SQL Statement*) b OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY;

The problem here is that the *Given SQL Statement" is unpredictable. It may or may not contain order by clause. I am not able to change the query result of this SQL Statement and I need to do pagination on it.

这里的问题是* Given SQL Statement“是不可预测的。它可能包含也可能不包含order by子句。我无法更改此SQL语句的查询结果,我需要对其进行分页。

I searched for solution on the Internet, but all of them suggested to use an arbitrary column, like primary key, in order by clause. But it will change the original order.

我在互联网上搜索了解决方案,但他们都建议按顺序使用任意列,如主键。但它会改变原来的秩序。

3 个解决方案

#1


2  

The short answer is that it can't be done, or at least can't be done properly.

简短的回答是它无法完成,或者至少无法正常完成。

The problem is that SQL Server (or any RDBMS) does not and can not guarantee the order of the records returned from a query without an order by clause.
This means that you can't use paging on such queries.
Further more, if you use an order by clause on a column that appears multiple times in your resultset, the order of the result set is still not guaranteed inside groups of values in said column - quick example:

问题是SQL Server(或任何RDBMS)不能也不能保证从没有order by子句的查询返回的记录的顺序。这意味着您无法对此类查询使用分页。此外,如果对结果集中多次出现的列使用order by子句,则仍无法保证结果集的顺序在所述列的值组中 - 快速示例:

;WITH cte (a, b)
AS
(
    SELECT 1, 'a'
    UNION ALL
    SELECT 1, 'b'
    UNION ALL
    SELECT 2, 'a'
    UNION ALL
    SELECT 2, 'b'
)

SELECT *
FROM cte 
ORDER BY a

Both result sets are valid, and you can't know in advance what will you get:

两个结果集都是有效的,您无法事先知道将获得什么:

a   b
-----
1   b
1   a
2   b
2   a

a   b
-----
1   a
1   b
2   a
2   b

(and of course, you might get other sorts)

(当然,你可能会得到其他种类)

#2


1  

The problem here is that the *Given SQL Statement" is unpredictable. It may or may not contain order by clause.

这里的问题是* Given SQL Statement“是不可预测的。它可能包含也可能不包含order by子句。

your inner query(unpredictable sql statement) should not contain order by,even if it contains,order is not guaranteed.

您的内部查询(不可预测的sql语句)不应包含order by,即使它包含,也不保证顺序。

To get guaranteed order,you have to order by some column.for the results to be deterministic,the ordered column/columns should be unique

要获得有保障的订单,您必须按某些列进行订购。为了使结果具有确定性,有序列/列应该是唯一的

#3


0  

Please note: what I'm about to suggest is probably horribly inefficient and should really only be used to help you go back to the project leader and tell them that pagination of an unordered query should not be done. Having said that...

请注意:我要提出的建议可能非常低效,并且应该只用于帮助您回到项目负责人并告诉他们不应该对无序查询进行分页。话说回来...


From your comments you say you are able to change the SQL statement before it is executed.

根据您的评论,您说您可以在执行之前更改SQL语句。

You could write the results of the original query to a temporary table, adding row count field to be used for subsequent pagination ordering.

您可以将原始查询的结果写入临时表,添加行计数字段以用于后续分页排序。

Therefore any original ordering is preserved and you can now paginate.

因此,保留任何原始排序,您现在可以分页。

But of course the reason for needing pagination in the first place is to avoid sending large amounts of data to the client application. Although this does prevent that, you will still be copying data to a temp table which, depending on the row size and count, could be very slow.

但当然,首先需要分页的原因是避免向客户端应用程序发送大量数据。虽然这确实可以防止这种情况,但您仍然会将数据复制到临时表,这取决于行的大小和计数,可能非常慢。

You also have the problem that the page size is coming from the client as part of the SQL statement. Parsing the statement to pick that out could be tricky.

您还遇到了页面大小来自客户端作为SQL语句的一部分的问题。解析声明来解决这个问题可能很棘手。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2017/03/14/9127f95b13e8e08725979b457a65b82.html



 
  © 2014-2022 ITdaan.com 联系我们: