Реалізація бази даних 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 містять елемент, який передбачає, що використовуються замовлення підзапитів:

Уникайте сортування, коли підзапит "ЗАМОВЛЕННЯ ПО" відповідає верхньому запиту

http://en.wikipedia.org/wiki/Order_by заявляє:

Хоча деякі системи баз даних дозволяють конкретизувати пункт ORDER BY у підселектах або переглядати визначення, наявність там не впливає.

Однак з моєї власної перевірки планів запитів:

  • SQL Server 2008 не підтримує ORDER BY у підзапиті
  • Postgres 9 підтримує ORDER BY в підзапиті
  • Oracle 10g підтримує ORDER BY у підзапиті

Отже, на моє запитання, чи є посилання, які можуть офіційно підтвердити або спростувати, що Postgres і Oracle не дозволяють сортувати в підзапиті?


2
Тільки тому, що ви дотримуєтесь певних результатів, це не гарантує їх. Якщо ви хочете послідовності, поставте порядок зовні. Період.
Аарон Бертран

В ідеалі саме це буде реалізовано. Однак, щоб дійти до цього етапу, буде задіяно зміни до основної логіки та багато драйверів баз даних. Оскільки про цю проблему не повідомлялося протягом багатьох років, здається, що деякі dbs послідовно реалізують ORDER BY у підзапитах. Було б непогано знати, які з них, якщо це можливо.
geographika

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, здається рецептом катастрофи. Не впевнений в аналогії автомобіля - вам потрібно додати, шукаючи його в посібнику, поки машина насправді летить ..
geographika

-1

Я визнаю, що це малорухливо, але якщо ви перебуваєте в крайній мірі, спробуйте повернути верхню кількість рядків у підзапиті. Повернення топ-100 відсотків не спрацьовує, але якщо ви хочете пройти проблему, ви можете запитати кількість рядків і передавати їх у ТОП як змінну. Я перевірив це на базі даних, встановленій на рівні сумісності 80, тому я думаю, що це має працювати з SQL 2000.

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

Я спробував це спочатку, і здавалося, що це добре для невеликих наборів даних. Однак, коли я отримував дуже великі набори записів, сортування знову стало випадковим у SQL Server 2008R2. Може стосується пам'яті / розмірів сторінки?
geographika

Вибачте, це не допомогло. Вибір перших 100 відсотків також призвів до сортування до випадкових випадків.
DBNull

Це не спрацює, якщо запит буде паралельним, особливо якщо Nameвін не є унікальним. Він може не продовжувати працювати серійно, якщо оптимізатор вибере інший індекс, з різним порядком ключових стовпців.
Ерік Дарлінг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.