sql >> Base de Datos >  >> RDS >> Mysql

Cómo usar ORDER BY dentro de UNION

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

para devolver filas en el orden en que nos gustaría que se devolvieran. es decir, MySQL parece respetar el ORDER BY cláusulas dentro de las vistas en línea.

Pero, sin un ORDER BY cláusula en la consulta más externa, el orden en que se devuelven las filas es no garantizado.

Si necesitamos que las filas se devuelvan en una secuencia particular, podemos 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.

Pero cuando tenemos un caso de uso en el que necesitamos que se devuelvan todas las filas de la primera consulta antes que 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.

SEGUIMIENTO

En su consulta original, 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 quiera.

El "truco" en consulta en mi respuesta (arriba) depende del comportamiento que puede ser específico de algunas versiones de MySQL.

Caso de prueba:

llenar 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 , de nuevo, "en orden".

Tenga en cuenta (nuevamente) que este comportamiento 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á a la totalidad conjunto de resultados.

Como mencioné anteriormente, si necesitara primero las filas de la primera consulta, seguidas de la segunda consulta, incluiría una columna "discriminadora" en cada consulta y luego incluiría la columna "discriminadora" 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