@ Папараццо понял это, но, возможно, я могу немного расширить их ответ.
Предложение ORDER BY PurchaseDate
не будет детерминированным , если любые две записи в вашей таблице имеют одинаковый PurchaseDate
, потому что порядок будет по-прежнему выполняться независимо от того, какая из этих двух записей SQL Server выберет вернись первым. В вашем случае, поскольку все ваших записей имеют одинаковые PurchaseDate
, SQL Server может вернуть эти записи в в любом порядке , и предложение будет выполнено. Другими словами, ваше предложение ORDER BY
не имеет смысла, за исключением того, что оно требуется для использования OFFSET...FETCH
.
Поскольку вы не можете точно знать, какой порядок будет производиться вашим предложением ORDER BY
, вы также не можете знать, куда конкретный OFFSET
поместит вас в этот порядок, что означает, что вы не можете знать, какие записи будут возвращены любой из трех ваших запросов. То, что SQL Server возвращает один и тот же набор результатов для каждого из ваших первых двух запросов, является допустимым поведением, но даже это не гарантируется каждый раз; Вы могли бы также легко получить другие результаты.
Если вам нужно гарантировать, что такие запросы будут возвращать непересекающиеся наборы, то вам нужно написать свое предложение ORDER BY
так, чтобы никакие две записи не имели одинаковую комбинацию значений для полей, по которым вы упорядочиваете. В вашем случае вы говорите, что у вас есть уникальный идентификатор для каждой строки, поэтому вы можете заказать сначала по 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
, чтобы получить непересекающиеся множества, потому что одного PurchaseDate
было бы достаточно, чтобы гарантировать уникальное упорядочение.