Реализация базы данных ORDER BY в подзапросе

10

Я использую приложение (MapServer - http://mapserver.org/ ), которое упаковывает операторы SQL, так что оператор ORDER BY находится во внутреннем запросе. Например

SELECT * FROM (
        SELECT ID, GEOM, Name
        FROM t
        ORDER BY Name
        ) as tbl

Приложение имеет много разных драйверов баз данных. В основном я использую драйвер MS SQL Server и SQL Server 2008. Это выдает ошибку, если в подзапросе найден ORDER BY.

Из MS Docs (хотя это для SQL Server 2000, он все еще кажется применимым):

Когда вы используете предложение ORDER BY в представлении, встроенной функции, производной таблице или подзапросе, это не гарантирует упорядоченный вывод. Вместо этого предложение ORDER BY используется только для гарантии того, что результирующий набор, сгенерированный оператором Top, имеет согласованную структуру. Предложение ORDER BY гарантирует упорядоченный результирующий набор только в том случае, если он указан в крайнем операторе SELECT.

Однако тот же тип запроса при запуске в Postgres (9) и Oracle возвращает результаты - в порядке, определенном в подзапросе. В Postgres план запроса показывает, что результаты отсортированы, а примечания к выпуску Postgres включают элемент, который подразумевает использование заказов подзапроса:

Избегайте сортировки, когда подзапрос ORDER BY соответствует верхнему запросу

http://en.wikipedia.org/wiki/Order_by гласит:

Хотя некоторые системы баз данных допускают указание предложения ORDER BY в подвыборах или определениях представлений, присутствие там не имеет никакого эффекта.

Однако из моей собственной проверки планов запросов:

  • SQL Server 2008 не поддерживает ORDER BY в подзапросе
  • Postgres 9 поддерживает ORDER BY в подзапросе
  • Oracle 10g поддерживает ORDER BY в подзапросе

Итак, мой вопрос: есть ли ссылки, которые могут официально подтвердить или опровергнуть то, что Postgres и Oracle не разрешают сортировку в подзапросе?

geographika
источник
2
То, что вы наблюдаете определенные результаты, не делает их гарантированными. Если вы хотите последовательности, разместите заказ снаружи. Период.
Аарон Бертран
В идеале это то, что будет реализовано. Однако для достижения этой стадии потребуются изменения в основной логике и многих драйверах базы данных. Поскольку об этой проблеме много лет не сообщалось, кажется, что некоторые базы данных последовательно реализуют ORDER BY в подзапросах. Было бы неплохо узнать, какие из них, если это возможно.
география
2
@geographika Даже если некоторые СУБД делают это последовательно до сих пор, нет никакой гарантии, что они будут продолжать делать то же самое в будущем. В качестве примера, усовершенствования оптимизатора MySQL в 5.6 (и MariaDB 5.3) идентифицируют ORDER BYв подзапросе как избыточный и не выполняют ненужную сортировку.
ypercubeᵀᴹ

Ответы:

15

Вы должны будете заставить свое приложение не помещать ORDER BYвнутрь подзапроса (возможно, у него есть возможность не использовать ненужный подзапрос в первую очередь). Как вы уже обнаружили, этот синтаксис не поддерживается в SQL Server без TOP. И с TOP, если вы не хотите пропустить некоторые строки, использование TOP 100 PERCENTв ORDER BYлюбом случае будет использовать оптимизированный.

А в Oracle и PostGres только то, что синтаксис поддерживается , не означает, что ему подчиняются. И только то, что вы наблюдаете за тем, как он подчиняется в каком-то сценарии, не означает, что он будет соблюдаться по мере появления новых версий или с небольшими изменениями в ваших данных, статистике, самом запросе или среде.

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

Вы просите ссылку, которая официально заявляет, что что-то не поддерживается. Это все равно что искать в руководстве по эксплуатации вашего автомобиля официальное заявление о том, что ваш автомобиль не может летать.

Аарон Бертран
источник
Спасибо. Я думаю, что MSSQL имеет правильный подход в выдаче ошибки. Как поддержка, так и реализация сортировки по внутренним запросам, когда она идет вразрез с основным принципом SQL, кажется катастрофой. Не уверен насчет автомобильной аналогии, хотя - вам нужно добавить поискать его в руководстве, когда машина действительно летит ..
география
-1

Я признаю, что это неряшливо, но если вы в затруднении, попробуйте вернуть наибольшее количество строк в подзапросе. Возврат верхних 100 процентов не работает, но если вы хотите решить проблему, вы можете запросить количество строк и передать их в TOP как переменную. Я проверил это на базе данных, настроенной на уровень совместимости 80, поэтому я думаю, что он должен работать с SQL 2000.

SELECT * FROM (
        SELECT TOP (100000) ID, GEOM, Name
        FROM t
        ORDER BY Name
        ) as tbl
DBNull
источник
Первоначально я попробовал это, и казалось, что он отлично подходит для небольших наборов данных. Однако когда я получал очень большие наборы записей, сортировка снова стала случайной в SQL Server 2008R2. Может относится к размерам памяти / страницы?
география
Извините, это не помогло. Выбор верхних 100 процентов также привел к тому, что сортировка стала случайной.
DBNull
Это не будет работать, если запрос идет параллельно, особенно если Nameон не уникален. Он может не работать последовательно, если оптимизатор выберет другой индекс с другим порядком ключевых столбцов.
Эрик Дарлинг