Могу ли я зависеть от порядка вывода при использовании row_number () - PullRequest
3 голосов
/ 10 июля 2009

Я думаю, что ответ нет . И я ищу пример счетчика , чтобы показать, что порядок вывода не гарантирован, если отсутствует порядок по предложению.

Рассмотрим:

create table #order (orderId int primary key clustered
    , customerId int not null -- references customer(customerId)
    , orderDateTIme datetime not null)

insert into #order values (1, 100, '2009-01-01')
insert into #order values (2, 101, '2009-01-02')
insert into #order values (3, 102, '2009-01-03')
insert into #order values (4, 103, '2009-01-04')
insert into #order values (5, 100, '2009-01-05')
insert into #order values (6, 101, '2009-01-06')
insert into #order values (7, 101, '2009-01-07')
insert into #order values (8, 103, '2009-01-08')
insert into #order values (9, 105, '2009-01-09')
insert into #order values (10, 100, '2009-01-10')
insert into #order values (11, 101, '2009-01-11')
insert into #order values (12, 102, '2009-01-12')
insert into #order values (13, 103, '2009-01-13')
insert into #order values (14, 100, '2009-01-14')
insert into #order values (15, 100, '2009-01-15')
insert into #order values (16, 101, '2009-01-16')
insert into #order values (17, 102, '2009-01-17')
insert into #order values (18, 101, '2009-01-18')
insert into #order values (19, 100, '2009-01-19')
insert into #order values (20, 101, '2009-01-20')

select * from #order
-- Results in PK order due to clustered primary key

select orderId, CustomerId, orderDateTime
    , row_number() over (partition by customerId order by orderDateTime) RN
from #order

В MS SQL Server 2005 порядок вывода имеет два свойства:

  1. Строки для каждого customerId смежный на выходе.

  2. Row_number() последовательно в каждый идентификатор клиента.

Насколько я понимаю, эти два свойства не гарантируются при отсутствии явного порядка по выражению. Я ищу пример, где вышеупомянутые свойства не сохраняются, что не вызвано предложением order by, а является лишь результатом того, как работает MS SQL Server. При необходимости разработайте собственное определение таблицы, индексы и т. Д. В вашем примере.

Или, если я ошибаюсь, ссылка на ссылку, которая показала бы, что эти упорядочения гарантированы, даже без явного порядка по условию.

Ответы [ 4 ]

10 голосов
/ 10 июля 2009

Если вы хотите упорядоченный результирующий набор, добавьте предложение ORDER BY к вашему SELECT . Период. Все остальное является косвенным и может работать, а может и не работать, в зависимости от текущей сборки SQL, которую вы тестируете, настроения оптимизатора и фазы перехода Марса в Рыбах.

Тривиальный пример, который противоречит вашему предположению:

select orderId, CustomerId, orderDateTime
    , row_number() over (partition by customerId order by orderDateTime) RN
    , row_number() over (partition by orderDateTime order by customerId) AntiRN
from #order
2 голосов
/ 10 июля 2009

Я изо всех сил пытаюсь найти уместность здесь; если вы хотите явно упорядочить, рекомендуется использовать в запросе предложение ORDER BY.

Я бы никогда не полагался на порядок таблиц по умолчанию при создании запроса, который основывался на порядке результатов. Любая современная СУБД сможет оптимизировать заказ на основе индексов и т. П., Поэтому об этом не стоит беспокоиться.

Что касается row_number, то побочным эффектом является то, что если предложение ORDER BY не существует, выходные данные упорядочиваются по значению ROW_NUMBER, вы не можете зависеть от этого поведения, поскольку это не гарантируется.

Опять же, только способ гарантировать порядок вывода с помощью предложения ORDER BY.

1 голос
/ 10 июля 2009

Как уже упоминалось, вы не можете полагаться на порядок строк без ORDER BY.

Однако вы можете положиться на функцию ROW_NUMBER () значение .

SELECT
    principal_id, name, 
    ROW_NUMBER() OVER (ORDER BY principal_id DESC) AS DemoRank
FROM
    msdb.sys.database_principals
ORDER BY
    name

Если вы используете данные в своем клиенте DemoRank, все будет в порядке, даже без предложения ORDER BY

Если вы полагаетесь на порядок набора записей (порядковый номер), то нет.

Приведенный выше пример дает первую строку (index = 0) как '##MS_PolicyEventProcessingLogin##', но использование значения DemoRank дает "db_denydatawriter"

В основном используйте ORDER BY.

0 голосов
/ 10 июля 2009

Если вы хотите, чтобы он был заказан, вы должны использовать ORDER BY.

просто посмотрите на план выполнения с

SET SHOWPLAN_ALL ON

если в столбце StmtText нет «order by», вы просто получаете вещи, как бы они ни были отсортированы после выполнения всей работы Иногда вам везет, иногда нет, с тем, как данные хранятся / загружаются / фильтруются / объединяются и т. Д. И как они возвращаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...