在带有OFFSET的Sql Server 2014 ORDER BY子句中,FETCH NEXT返回奇怪的结果

时间:2016-05-12 10:29:44

标签: sql sql-server

我目前正在使用Sql Server 2014 Professional,当前版本为(12.0.4100)。我有一个View,我正在尝试选择具有特定偏移量的10行。
我的视图如下所示:

    BeginTime   |     EndTime    | Duration |   Name   
09:00:00.0000000|16:00:00.0000000|    1     | some_name1
09:00:00.0000000|16:00:00.0000000|    2     | some_name2
09:00:00.0000000|16:00:00.0000000|    3     | some_name3
09:00:00.0000000|16:00:00.0000000|    4     | some_name4
09:00:00.0000000|16:00:00.0000000|    5     | some_name5
09:00:00.0000000|16:00:00.0000000|    6     | some_name6
09:00:00.0000000|16:00:00.0000000|    7     | some_name7

这些行有100行,并且在BeginTimeEndTime中都具有完全相同的值。相关表格中的持续时间从1增加到100.如果查询只是:

SELECT * FROM View_Name

ResultSet是正确的。我可以通过检查持续时间栏来理解它。

如果我想从0开始只获取10行,则ResultSet是正确的,从最多18开始是正确的。当我想从19或19以上获取10行时,ResultSet中的持续时间返回不相关的结果,如持续时间反转。但它永远不会返回持续时间超过11的行。  我用来获取特定行的查询如下:

SELECT * FROM View_Name ORDER BY BeginTime ASC OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY

在这种情况下也有一些奇怪的事情;如果我指定USE master,则此问题会消失,但是,如果我指定USE [mydb_name],则会再次出现问题。
顺便说一下,我在我的本地电脑上使用SQL SERVER 2014 Professional v(12.0.2269),这个问题在上述情况下消失了。

PS:我无法使用USE master,因为我在存储过程中动态创建和列出视图。
任何帮助,答案或评论都将被接受。
谢谢!

2 个答案:

答案 0 :(得分:13)

documentation解释说:

  

使用OFFSET和{。}在查询请求之间获得稳定的结果   FETCH,必须满足以下条件:

     

。 。

     
      
  1. ORDER BY子句包含保证唯一的列或列组合。
  2.   

在您的情况下,BeginTime不是唯一的。一般数据库 - 特别是SQL Server - 不实现稳定的排序。稳定排序是当键相同时行以相同顺序排序的排序。这很明显,因为表和结果集代表无序集。它们没有固有的顺序。

因此,您需要一个唯一的密钥才能使排序稳定。根据您的数据,这似乎是durationname或两者:

SELECT * 
ROM View_Name
ORDER BY BeginTime ASC, Duration, Name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

答案 1 :(得分:0)

您的订单应该是唯一的,否则您将得到不确定的结果(在您的情况下,开始时间不是唯一的,并且您不保证每次都获得相同的结果)。将您的查询更改为下面以使其独特。

SELECT * FROM View_Name ORDER BY duration OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY

除此之外,您的第一个查询(从视图中选择*)结果集并不保证每次都是准确的,除非您有一个外部订单。