Något sådant här borde fungera i MySQL:
SELECT a.*
FROM (
SELECT ... FROM ... ORDER BY ...
) a
UNION ALL
SELECT b.*
FROM (
SELECT ... FROM ... ORDER BY ...
) b
för att returnera rader i en ordning som vi vill att de ska returneras. dvs MySQL verkar hedra ORDER BY
satser i inline-vyerna.
Men utan en ORDER BY
sats på den yttersta frågan, ordningen som raderna returneras är inte garanterat.
Om vi behöver raderna returnerade i en viss sekvens kan vi inkludera en ORDER BY
på den yttersta frågan. I många användningsfall kan vi bara använda en ORDER BY
på den yttersta frågan för att tillfredsställa resultaten.
Men när vi har ett användningsfall där vi behöver alla rader från den första frågan returnerade före alla rader från den andra frågan, är ett alternativ att inkludera en extra diskriminatorkolumn i var och en av frågorna. Till exempel, lägg till ,'a' AS src
i den första frågan, ,'b' AS src
till den andra frågan.
Då kan den yttersta frågan inkludera ORDER BY src, name
, för att garantera sekvensen av resultaten.
UPPFÖLJNING
I din ursprungliga fråga, ORDER BY
i dina frågor kasseras av optimeraren; eftersom det inte finns någon ORDER BY
tillämpas på den yttre frågan, är MySQL fri att returnera raderna i vilken ordning den vill.
"Knepet" i frågan i mitt svar (ovan) är beroende av beteende som kan vara specifikt för vissa versioner av MySQL.
Testfall:
fylla i tabeller
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');
fråga
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
resultatuppsättningen returnerades
id role
------ ---------
3 aragorn
2 frodo
5 gandalf
4 pippin
1 sam
2 boromir
3 elron
1 gimli
5 legolas
4 merry
Raderna från foo2
returneras "i ordning", följt av raderna från foo3
, återigen, "i ordning".
Observera (igen) att detta beteende INTE är garanterat. (Beteendet vi observerar är en bieffekt av hur MySQL bearbetar inline-vyer (härledda tabeller). Detta beteende kan vara annorlunda i versioner efter 5.5.)
Om du vill att raderna ska returneras i en viss ordning, anger du en ORDER BY
klausul för den yttersta frågan. Och den beställningen kommer att gälla för hela resultat.
Som jag nämnde tidigare, om jag behövde raderna från den första frågan först, följt av den andra frågan, skulle jag inkludera en "diskriminator"-kolumn i varje fråga och sedan inkludera "diskriminator"-kolumnen i ORDER BY-satsen. Jag skulle också avskaffa de inbyggda vyerna och göra något så här:
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