Użycie ORDER BY
klauzuli wewnątrz zapytania podrzędnego w połączeniu z UNION
mysql zoptymalizuje ORDER BY
klauzulę.
Dzieje się tak, ponieważ domyślnie a UNION
zwraca nieuporządkowaną listę, więc ORDER BY
nie zrobiłby nic.
Optymalizacja jest wspomniana w dokumentacji i mówi:
Aby zastosować ORDER BY lub LIMIT do pojedynczego polecenia SELECT, umieść klauzulę w nawiasach, które otaczają 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);
Jednak użycie ORDER BY dla poszczególnych instrukcji SELECT nie oznacza nic o kolejności, w jakiej wiersze pojawiają się w wyniku końcowym, ponieważ funkcja UNION domyślnie tworzy nieuporządkowany zestaw wierszy. Dlatego użycie ORDER BY w tym kontekście jest zwykle w połączeniu z LIMIT, więc jest używane do określenia podzbioru wybranych wierszy do pobrania dla polecenia SELECT, nawet jeśli niekoniecznie wpływa na kolejność tych wierszy w ostateczny wynik UNION. Jeśli ORDER BY pojawia się bez LIMIT w SELECT, jest zoptymalizowany, ponieważ i tak nie będzie miał żadnego efektu.
Ostatnie zdanie jest trochę mylące, ponieważ powinno mieć skutek. Ta optymalizacja powoduje problem w sytuacji, w której musisz złożyć zamówienie w podzapytaniu.
Aby zmusić MySQL do nie przeprowadzania tej optymalizacji, możesz dodać klauzulę LIMIT w następujący sposób:
(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)
Wysoka LIMIT
oznacza, że możesz dodać OFFSET
do ogólnego zapytania, jeśli chcesz zrobić coś, na przykład paginację.
Daje to również dodatkową korzyść w postaci możliwości ORDER BY
różnych kolumn dla każdej unii.