Якщо ви використовуєте ORDER BY
пункт усередині підзапиту, який використовується спільно з UNION
mysql, це оптимізує ORDER BY
застереження.
Це тому, що за замовчуванням a UNION
повертає не упорядкований список, тому, таким чином ORDER BY
, нічого не буде робити.
Оптимізація згадується в документах і говорить:
Щоб застосувати ЗАМОВЛЕННЯ ВІД або ОБМЕЖЕННЯ до окремого 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 відображається без ОБМЕЖЕННЯ в 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
різні стовпці для кожного союзу.