Solución:
Algo como esto debería funcionar en MySQL:
SELECT a.*
FROM (
SELECT ... FROM ... ORDER BY ...
) a
UNION ALL
SELECT b.*
FROM (
SELECT ... FROM ... ORDER BY ...
) b
Sin embargo, tenga en cuenta que en ausencia ORDER BY
(o GROUP BY
) en la consulta más externa, el orden en que se devuelven las filas es NO garantizado.
Si necesita que las filas se devuelvan en una secuencia en particular, debe incluir un ORDER BY
en la consulta más externa. En muchos casos de uso, podemos usar un ORDER BY
en la consulta más externa para satisfacer los resultados.
Sin embargo, si tiene un caso de uso en el que necesita que se devuelvan todas las filas de la primera consulta antes de todas las filas de la segunda consulta, una opción es incluir una columna discriminadora adicional en cada una de las consultas. Por ejemplo, agregue ,'a' AS src
en la primera consulta, ,'b' AS src
a la segunda consulta.
Entonces la consulta más externa podría incluir ORDER BY src, name
, para garantizar la secuencia de los resultados.
HACER UN SEGUIMIENTO
En su consulta original, el ORDER BY
en sus consultas es descartado por el optimizador; ya que no hay ORDER BY
aplicado a la consulta externa, MySQL es libre de devolver las filas en el orden que desee.
El “truco” en la consulta en mi respuesta (arriba) depende del comportamiento que puede ser específico de algunas versiones de MySQL.
Caso de prueba:
poblar tablas
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');
consulta
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
conjunto de resultados devuelto
id role
------ ---------
3 aragorn
2 frodo
5 gandalf
4 pippin
1 sam
2 boromir
3 elron
1 gimli
5 legolas
4 merry
Las filas de foo2
se devuelven “en orden”, seguidos de las filas de foo3
, nuevamente, “en orden”.
Tenga en cuenta (de nuevo) que este comportamiento es NO garantizado. (El comportamiento que observamos es un efecto secundario de cómo MySQL procesa las vistas en línea (tablas derivadas). Este comportamiento puede ser diferente en las versiones posteriores a la 5.5).
Si necesita que las filas se devuelvan en un orden particular, especifique un ORDER BY
cláusula para la consulta más externa. Y ese orden se aplicará al completo conjunto resultante.
Como mencioné anteriormente, si primero necesitara las filas de la primera consulta, seguidas de la segunda, incluiría una columna de “discriminador” en cada consulta y luego incluiría la columna de “discriminador” en la cláusula ORDER BY. También eliminaría las vistas en línea y haría algo como esto:
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
Solo usa un ORDER BY al final.
La Unión convierte dos selecciones en una selección lógica. El orden se aplica a todo el conjunto, no a cada parte.
Tampoco use ningún parens. Solo:
SELECT 1 as Origin, blah blah FROM foo WHERE x
UNION ALL
SELECT 2 as Origin, blah blah FROM foo WHERE y
ORDER BY Origin, z
No use ORDER BY
en un individuo SELECT
declaración dentro de un UNION
, a menos que estés usando LIMIT
con eso.
Los documentos de MySQL en UNION explican por qué (el énfasis es mío):
Para aplicar ORDER BY o LIMIT a un SELECT individual, coloque la cláusula dentro del paréntesis que encierra el 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);
Sin embargo, el uso de ORDER BY para instrucciones SELECT individuales no implica nada sobre el orden en el que aparecen las filas en el resultado final porque UNION de forma predeterminada produce un conjunto de filas desordenado. Por lo tanto, el uso de ORDER BY en este contexto es típicamente junto con LIMIT, por lo que se usa para determinar el subconjunto de las filas seleccionadas para recuperar para SELECT, aunque no necesariamente afecta el orden de esas filas en el resultado final de UNION. Si ORDER BY aparece sin LIMIT en un SELECT, se optimiza porque no tendrá ningún efecto de todos modos.
Para usar una cláusula ORDER BY o LIMIT para ordenar o limitar todo el resultado de UNION, entre paréntesis las declaraciones SELECT individuales y coloque ORDER BY o LIMIT después de la última. El siguiente ejemplo usa ambas cláusulas:
(SELECT a FROM t1 WHERE a=10 AND B=1) UNION (SELECT a FROM t2 WHERE a=11 AND B=2) ORDER BY a LIMIT 10;
Parece un ORDER BY
cláusula como la siguiente le dará lo que desea:
ORDER BY user_id, name