Sesuatu seperti ini seharusnya bekerja di MySQL:
SELECT a.*
FROM (
SELECT ... FROM ... ORDER BY ...
) a
UNION ALL
SELECT b.*
FROM (
SELECT ... FROM ... ORDER BY ...
) b
untuk mengembalikan baris dalam urutan yang kami inginkan. yaitu MySQL tampaknya menghormati ORDER BY
klausa di dalam tampilan sebaris.
Namun, tanpa ORDER BY
klausa pada kueri terluar, urutan baris yang dikembalikan adalah bukan dijamin.
Jika kita membutuhkan baris yang dikembalikan dalam urutan tertentu, kita dapat menyertakan ORDER BY
pada kueri terluar. Dalam banyak kasus penggunaan, kita cukup menggunakan ORDER BY
pada kueri terluar untuk memenuhi hasil.
Tetapi ketika kami memiliki kasus penggunaan di mana kami membutuhkan semua baris dari kueri pertama dikembalikan sebelum semua baris dari kueri kedua, satu opsi adalah menyertakan kolom diskriminator tambahan di setiap kueri. Misalnya, tambahkan ,'a' AS src
dalam kueri pertama, ,'b' AS src
ke kueri kedua.
Kemudian kueri terluar dapat menyertakan ORDER BY src, name
, untuk menjamin urutan hasil.
TINDAK LANJUT
Dalam kueri asli Anda, ORDER BY
dalam kueri Anda dibuang oleh pengoptimal; karena tidak ada ORDER BY
diterapkan pada kueri luar, MySQL bebas mengembalikan baris dalam urutan apa pun yang diinginkan.
"Trik" dalam kueri dalam jawaban saya (di atas) bergantung pada perilaku yang mungkin spesifik untuk beberapa versi MySQL.
Kasus uji:
mengisi tabel
CREATE TABLE foo2 (id INT PRIMARY KEY, role VARCHAR(20)) ENGINE=InnoDB;
CREATE TABLE foo3 (id INT PRIMARY KEY, role VARCHAR(20)) ENGINE=InnoDB;
INSERT INTO foo2 (id, role) VALUES
(1,'sam'),(2,'frodo'),(3,'aragorn'),(4,'pippin'),(5,'gandalf');
INSERT INTO foo3 (id, role) VALUES
(1,'gimli'),(2,'boromir'),(3,'elron'),(4,'merry'),(5,'legolas');
permintaan
SELECT a.*
FROM ( SELECT s.id, s.role
FROM foo2 s
ORDER BY s.role
) a
UNION ALL
SELECT b.*
FROM ( SELECT t.id, t.role
FROM foo3 t
ORDER BY t.role
) b
hasil yang dikembalikan
id role
------ ---------
3 aragorn
2 frodo
5 gandalf
4 pippin
1 sam
2 boromir
3 elron
1 gimli
5 legolas
4 merry
Baris dari foo2
dikembalikan "dalam urutan", diikuti oleh baris dari foo3
, sekali lagi, "berurutan".
Perhatikan (sekali lagi) bahwa perilaku ini TIDAK terjamin. (Perilaku yang kami amati adalah efek samping dari cara MySQL memproses tampilan sebaris (tabel turunan). Perilaku ini mungkin berbeda di versi setelah 5.5.)
Jika Anda membutuhkan baris yang dikembalikan dalam urutan tertentu, tentukan ORDER BY
klausa untuk kueri terluar. Dan pemesanan itu akan berlaku untuk seluruh kumpulan hasil.
Seperti yang saya sebutkan sebelumnya, jika saya membutuhkan baris dari kueri pertama terlebih dahulu, diikuti oleh kueri kedua, saya akan menyertakan kolom "diskriminator" di setiap kueri, dan kemudian menyertakan kolom "diskriminator" di klausa ORDER BY. Saya juga akan menghapus tampilan sebaris, dan melakukan sesuatu seperti ini:
SELECT s.id, s.role, 's' AS src
FROM foo2 s
UNION ALL
SELECT t.id, t.role, 't' AS src
FROM foo3 t
ORDER BY src, role