Если вы выполняете простой SELECT-WHERE на уже отсортированном CTE, гарантированно ли ваши результаты будут в том же порядке, только что отфильтрованы? - PullRequest
1 голос
/ 02 мая 2020

Интересно об ожидаемом / детерминированном c порядке вывода из Oracle 11g для запросов на основе отсортированных CTE.

Рассмотрим этот (чрезвычайно упрощенный ради) пример запроса SQL. Опять же, обратите внимание, что в CTE есть предложение ORDER BY.

WITH SortedArticles as (
    SELECT.  *
    FROM     Articles
    ORDER BY DatePublished
)
SELECT *
FROM   SortedArticles
WHERE  Author = 'Joe';

Можно ли предположить, что выведенные строки гарантированно будут в том же порядке, что и CTE, или мне придется повторно -сортировать их во второй раз?

Опять же, это чрезвычайно упрощенный пример, но он содержит важные части того, что я спрашиваю. Это ...

  1. CTE отсортирован
  2. Последний оператор SELECT выбирает только CTE, ничего больше (без объединений и т. Д. c.) И
  3. В последнем операторе SELECT указано только предложение WHERE. Это чисто фильтрующий оператор.

Ответы [ 2 ]

2 голосов
/ 02 мая 2020

Короткий ответ - нет. Единственный способ гарантировать заказ - это предложение ORDER BY в вашем внешнем запросе. Но в этой ситуации нет необходимости сортировать результаты в CTE.

Однако, если выражение сортировки является сложным, и вам требуется сортировка в производных CTE (например, из-за использования OFFSET/FETCH или ROWNUM), вы могли бы упростить последующую сортировку, добавив поле номера строки к исходному CTE на основе его критериев сортировки, а затем просто отсортировав полученные CTE по этому номеру строки. Для вашего примера:

WITH SortedArticles as (
    SELECT *,
           ROW_NUMBER() OVER (ORDER BY DatePublished) AS rn
    FROM Articles
)
SELECT *
FROM SortedArticles
WHERE Author = 'Joe'
ORDER BY rn
0 голосов
/ 02 мая 2020

Нет, результаты не гарантируются в том же порядке, что и в подзапросе. Никогда не было, никогда не будет. Вы можете наблюдать определенное поведение, особенно если CTE материализован, на который вы можете попытаться повлиять с помощью подсказок оптимизатора, таких как /*+ MATERIALIZE */ и /*+ INLINE */. Однако поведение оптимизатора запросов зависит также от объема данных, скорости ввода-вывода и, самое главное, от версии базы данных. Например, Oracle 12.2 представляет функцию, называемую «Темп-таблица длительности курсора в памяти», которая пытается ускорить запросы, подобные вашим, без сохранения порядка в подзапросе.

Я бы go вдоль с предложением @ Ника добавить поле номера строки в подзапросе.

...