Quelque chose comme ceci devrait fonctionner dans MySQL :
SELECT a.*
FROM (
SELECT ... FROM ... ORDER BY ...
) a
UNION ALL
SELECT b.*
FROM (
SELECT ... FROM ... ORDER BY ...
) b
pour renvoyer les lignes dans un ordre dans lequel nous aimerions qu'elles soient renvoyées. c'est-à-dire que MySQL semble respecter le ORDER BY
clauses à l'intérieur des vues en ligne.
Mais, sans ORDER BY
clause sur la requête la plus externe, l'ordre dans lequel les lignes sont renvoyées n'est pas garanti.
Si nous avons besoin que les lignes soient renvoyées dans une séquence particulière, nous pouvons inclure un ORDER BY
sur la requête la plus externe. Dans de nombreux cas d'utilisation, nous pouvons simplement utiliser un ORDER BY
sur la requête la plus externe pour satisfaire les résultats.
Mais lorsque nous avons un cas d'utilisation où nous avons besoin que toutes les lignes de la première requête soient renvoyées avant toutes les lignes de la deuxième requête, une option consiste à inclure une colonne de discriminateur supplémentaire dans chacune des requêtes. Par exemple, ajoutez ,'a' AS src
dans la première requête, ,'b' AS src
à la deuxième requête.
Ensuite, la requête la plus externe pourrait inclure ORDER BY src, name
, pour garantir l'enchaînement des résultats.
SUIVI
Dans votre requête d'origine, le ORDER BY
dans vos requêtes est ignoré par l'optimiseur ; puisqu'il n'y a pas de ORDER BY
appliqué à la requête externe, MySQL est libre de renvoyer les lignes dans l'ordre qu'il souhaite.
Le "truc" de la requête dans ma réponse (ci-dessus) dépend du comportement qui peut être spécifique à certaines versions de MySQL.
Scénario de test :
remplir les tableaux
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');
requête
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
jeu de résultats renvoyé
id role
------ ---------
3 aragorn
2 frodo
5 gandalf
4 pippin
1 sam
2 boromir
3 elron
1 gimli
5 legolas
4 merry
Les lignes de foo2
sont renvoyés "dans l'ordre", suivis des lignes de foo3
, encore une fois, "dans l'ordre".
Notez (encore) que ce comportement n'est PAS garanti. (Le comportement que nous observons est un effet secondaire de la façon dont MySQL traite les vues en ligne (tables dérivées). Ce comportement peut être différent dans les versions postérieures à la 5.5.)
Si vous avez besoin que les lignes soient renvoyées dans un ordre particulier, spécifiez un ORDER BY
clause pour la requête la plus externe. Et cet ordre s'appliquera à l'intégralité jeu de résultats.
Comme je l'ai mentionné précédemment, si j'avais d'abord besoin des lignes de la première requête, suivies de la deuxième requête, j'inclurais une colonne "discriminateur" dans chaque requête, puis j'inclurais la colonne "discriminateur" dans la clause ORDER BY. Je supprimerais également les vues en ligne et ferais quelque chose comme ceci :
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