При использовании предложения ORDER BY
внутри подзапроса, используемого вместе с UNION
, mysql оптимизирует предложение ORDER BY
.
Это потому, что по умолчанию UNION
возвращает неупорядоченный список, поэтому ORDER BY
ничего не будет делать.
Оптимизация упоминается в документах и гласит:
Чтобы применить ORDER BY или LIMIT к отдельному SELECT, поместите предложение
внутри скобок, которые заключают в себе SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
Однако использование ORDER BY для отдельных операторов SELECT подразумевает
ничего о порядке, в котором строки появляются в конечном результате
потому что UNION по умолчанию создает неупорядоченный набор строк. Следовательно,
использование ORDER BY в этом контексте обычно связано с
LIMIT, так что он используется для определения подмножества выбранных строк
извлечь для SELECT, даже если это не обязательно влияет
порядок этих строк в конечном результате UNION. Если появляется ORDER BY
без LIMIT в SELECT, он оптимизируется, потому что он будет иметь
никакого эффекта в любом случае.
Последнее предложение немного вводит в заблуждение, потому что оно должно иметь эффект. Эта оптимизация вызывает проблему, когда вы находитесь в ситуации, когда вам нужно сделать заказ внутри подзапроса.
Чтобы заставить MySQL не выполнять эту оптимизацию, вы можете добавить предложение LIMIT следующим образом:
(SELECT 1 AS rank, id, add_date FROM my_table WHERE distance < 5 ORDER BY add_date LIMIT 9999999999)
UNION ALL
(SELECT 2 AS rank, id, add_date FROM my_table WHERE distance BETWEEN 5 AND 15 ORDER BY rank LIMIT 9999999999)
UNION ALL
(SELECT 3 AS rank, id, add_date from my_table WHERE distance BETWEEN 5 and 15 ORDER BY id LIMIT 9999999999)
Высокий LIMIT
означает, что вы можете добавить OFFSET
к полному запросу, если хотите сделать что-то, например, нумерацию страниц.
Это также дает вам дополнительное преимущество, заключающееся в возможности ORDER BY
различных столбцов для каждого союза.