我正在使用SQL Server,在表Purchase
中,我有大约50条记录。
我试图获取前20(0-20),然后20-40,最后是最后10。
我拥有的SQL命令是:
SELECT * FROM Purchase WHERE dataOK = 'OK' ORDER BY PurchaseDate DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY
SELECT * FROM Purchase WHERE dataOK = 'OK' ORDER BY PurchaseDate DESC OFFSET 19 ROWS FETCH NEXT 20 ROWS ONLY
SELECT * FROM Purchase WHERE dataOK = 'OK' ORDER BY PurchaseDate DESC OFFSET 39 ROWS FETCH NEXT 20 ROWS ONLY
我不知道为什么,但前两个命令返回完全相同的记录。 为什么它没有显示两组不同的结果?
编辑:
好的,我知道XX
中的FETCH XX
是要返回的行数。但是我的SQL服务器返回的结果与上面的前两个命令完全相同。
答案 0 :(得分:1)
返回的行数由命令的FETCH
部分确定。这是行数。它不是偏移的位置。
因此,如果您想要20行,那么您将始终拥有FETCH NEXT 20 ROWS ONLY
。
前两个不应该返回相同的结果。 。 。虽然如果只看PurchaseDate
,某些结果可能看起来相同。
答案 1 :(得分:1)
如果PurchaseDate不是唯一的,那么该组中的订单不能保证重复 将ID添加到排序中以获得可重复的排序。
SELECT * FROM Purchase WHERE dataOK = 'OK'
ORDER BY PurchaseDate DESC, ID
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY
SELECT * FROM Purchase WHERE dataOK = 'OK'
ORDER BY PurchaseDate DESC, ID
OFFSET 19 ROWS FETCH NEXT 20 ROWS ONLY
SELECT * FROM Purchase WHERE dataOK = 'OK'
ORDER BY PurchaseDate DESC, ID
OFFSET 39 ROWS FETCH NEXT 20 ROWS ONLY
答案 2 :(得分:0)
我会重写为
SELECT *
FROM Purchase
WHERE dataOK = 'OK'
ORDER BY PurchaseDate DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY
GO
SELECT *
FROM Purchase
WHERE dataOK = 'OK'
ORDER BY PurchaseDate DESC OFFSET 19 ROWS FETCH NEXT 21 ROWS ONLY
SELECT *
FROM Purchase
WHERE dataOK = 'OK'
ORDER BY PurchaseDate DESC OFFSET 40 ROWS FETCH NEXT 10 ROWS ONLY
答案 3 :(得分:0)
@paparazzo已经解决了这个问题,但也许我可以稍微扩展他们的答案。
如果表中的任何两条记录具有相同的ORDER BY PurchaseDate
,则PurchaseDate
子句将不是deterministic,因为无论SQL Server中的哪两条记录,仍然会满足排序选择先退回。在您的情况下,由于所有记录具有相同的PurchaseDate
,因此SQL Server可以在任何顺序中返回这些记录,并且该子句将得到满足。换句话说,您的ORDER BY
条款没有任何意义,除非您需要使用OFFSET...FETCH
条款才能使用ORDER BY
。
因为您无法准确知道OFFSET
子句将产生什么排序,您也无法知道特定ORDER BY
将在哪个排序中进行排序,这意味着您无法知道哪些记录将会由三个查询的任何返回。 SQL Server为前两个查询返回相同的结果集是合法行为,但即使这样也不能保证每次都发生;你可以很容易地得到不同的结果。
如果您需要保证此类查询将返回不相交的集合,那么您需要编写PurchaseDate
子句,使得没有两个记录对您要订购的字段具有相同的值组合。在您的情况下,您说每行有一个唯一标识符,因此您可以先按-- Create sample data: 50 records with unique RowNumber values and the same PurchaseDate value.
declare @Purchase table (RowNumber int, PurchaseDate date);
with Numbers as (select top 50 RowNumber = row_number() over (order by (select null)) from sys.objects)
insert @Purchase
select
RowNumber,
PurchaseDate = /*dateadd(day, RowNumber,*/ convert(date, getdate())/*)*/
from
Numbers;
-- These result sets are nondeterministic because all the PurchaseDate values are the same, which
-- means that the records may be returned in any order and the ORDER BY will be satisfied.
select * from @Purchase order by PurchaseDate offset 0 rows fetch next 20 rows only;
select * from @Purchase order by PurchaseDate offset 20 rows fetch next 20 rows only;
select * from @Purchase order by PurchaseDate offset 40 rows fetch next 20 rows only;
-- Adding the unique RowNumber to my ORDER BY clause makes the results deterministic and therefore
-- guarantees that the following result sets will be rows 1-20, 21-40, and 41-50, respectively.
select * from @Purchase order by PurchaseDate, RowNumber offset 0 rows fetch next 20 rows only;
select * from @Purchase order by PurchaseDate, RowNumber offset 20 rows fetch next 20 rows only;
select * from @Purchase order by PurchaseDate, RowNumber offset 40 rows fetch next 20 rows only;
排序,然后按该标识符排序,您的查询将适用于您。这是一个例子:
PurchaseDate
请注意,如果我要取消注释分配PurchaseDate
值的行的已注释部分,这会为每行提供唯一的RowNumber
,那么我就不需要包含{我的ORDER BY
子句中的{1}}是为了得到不相交的集合,因为仅PurchaseDate
就足以保证唯一的排序。