SQL Server UNION - Что такое поведение по умолчанию ORDER BY - PullRequest
34 голосов
/ 07 января 2009

Если у меня есть несколько утверждений UNION в качестве надуманного примера:

SELECT * FROM xxx WHERE z = 1
UNION 
SELECT * FROM xxx WHERE z = 2
UNION
SELECT * FROM xxx WHERE z = 3

Какое поведение по умолчанию order by?

Тестовые данные, которые я вижу, по существу не возвращают данные в порядке, указанном выше. То есть данные упорядочены, но я хотел знать, каковы правила приоритета на этом.

Другое дело, что в этом случае xxx - это View. Представление объединяет 3 разные таблицы, чтобы получить нужные результаты.

Ответы [ 7 ]

42 голосов
/ 07 января 2009

Нет заказа по умолчанию.

Без условия Order By возвращаемый заказ не определен. Это означает, что SQL Server может вернуть их в любом порядке.

EDIT: Исходя из того, что я видел, без Order By, порядок возврата результатов зависит от плана запроса. Таким образом, если есть индекс, который он использует, результат может вернуться в таком порядке, но опять же нет никакой гарантии.

15 голосов
/ 08 января 2009

В отношении добавления предложения ORDER BY:

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

Например:

SELECT 1, * FROM xxx WHERE z = 'abc'
UNION ALL
SELECT 2, * FROM xxx WHERE z = 'def'
UNION ALL
SELECT 3, * FROM xxx WHERE z = 'ghi'
ORDER BY 1

Пустой порядковый столбец также полезен для случаев, когда я собираюсь выполнить два запроса, и я знаю, что только один будет возвращать какие-либо результаты. Тогда я могу просто проверить порядковый номер возвращаемых результатов. Это избавляет меня от необходимости выполнять несколько вызовов базы данных и проводить проверку большинства пустых результатов.

10 голосов
/ 11 марта 2009

Только что нашел фактический ответ.

Поскольку UNION удаляет дубликаты, он выполняет ОТЛИЧНУЮ СОРТИРОВКУ. Это делается до того, как все операторы UNION будут объединены (ознакомьтесь с планом выполнения).

Чтобы остановить сортировку, выполните UNION ALL, и это также не удалит дубликаты.

7 голосов
/ 07 января 2009

Если вас волнует, в каком порядке возвращаются записи, вы ДОЛЖНЫ использовать заказ по.

Если вы не включите его, он может показаться организованным (на основе индексов, выбранных планом запроса), но результаты, которые вы видите сегодня, НЕ МОГУТ быть ожидаемыми результатами и даже могут изменить когда тот же запрос будет запущен завтра.

Редактировать: Несколько хороших, конкретных примеров: (все примеры - сервер MS SQL)

  • Блог Дэйва Пинала описывает, как два очень похожих запроса могут показывать различный очевидный порядок, поскольку используются разные индексы:

    SELECT ContactID FROM Person.Contact
    SELECT *         FROM Person.Contact
    
  • Конор Каннингем показывает, как видимый порядок может измениться, когда таблица станет больше (если оптимизатор запросов решит использовать план параллельного выполнения).

  • Уго Корнелис доказывает, что видимый порядок не всегда основан на первичном ключе. Вот его следующий пост с объяснением.

2 голосов
/ 07 января 2009

UNION может быть обманчивым по отношению к порядку набора результатов, потому что база данных иногда использует метод сортировки для предоставления DISTINCT, который неявно присутствует в UNION, что делает его похожим на преднамеренно упорядоченные строки - это не применяется ОБЪЕДИНЯТЬ ВСЕХ, для которых, конечно, не существует явного и неявного различия.

Однако существуют алгоритмы для неявного отличия, такие как метод хеширования Oracle в 10g +, для которого упорядочение не будет применяться.

Как говорит DJ, всегда используйте ORDER BY

1 голос
/ 07 января 2009

Очень часто встречается плохо написанный код, который предполагает, что данные таблиц возвращаются в порядке вставки, и 95% времени кодер сходит с рук и никогда не осознает, что это проблема, как во многих распространенных базах данных (MSSQL , Oracle, MySQL). Это, конечно, полная ошибка, и следует всегда исправлять, когда она встречается, и всегда, без исключения, использовать предложение Order By самостоятельно.

0 голосов
/ 22 июля 2014

Из моего практического опыта вы можете изменить порядок, используя «UNION» против «UNION ALL» ... т.е. если ваш запрос похож на

Select Count(*) from Table A
UNION 
Select Count(*) from Table B

result is
10
26

Вы можете изменить заказ, заменив «UNION» на «UNION ALL» ... тогда результат будет

26
10
...