¿Cómo ordenar por con union en SQL?

202

¿Es posible ordenar cuando los datos provienen de muchos seleccionados y unirlos? Como

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"

¿Cómo puedo ordenar esta consulta por nombre?

Algunos dijeron que puede consultar este aspecto.

Select id,name,age
From Student
Where age < 15 or name like "%a%"
Order by name

Pero en este caso simplemente ignoro esa solución.

Guilgamos
fuente
1
Si tiene la misma columna en la consulta de unión, al final, ordene por el nombre de su columna.
anirban karak

Respuestas:

266

Solo escribe

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"
Order by name

el orden por se aplica al conjunto de resultados completo

bernd_k
fuente
45
¿Qué sucede si deseo que la clasificación se aplique solo en la parte superior de UNION?
marifrahman
77
@marifrahman mira mi respuesta stackoverflow.com/a/43855496/2340825
BA TabNabber
2
@marifrahman lamento excavar un viejo tema, pero puede ayudar a otros. En caso de que desee que ORDER BY se aplique a la primera parte de UNION, proteja este SELECT con paréntesis.
Lideln Kyoku
82
Select id,name,age
from
(
   Select id,name,age
   From Student
   Where age < 15
  Union
   Select id,name,age
   From Student
   Where Name like "%a%"
) results
order by name
Mark Robinson
fuente
46
Como señaló bernd_k, por definición, los SELECT individuales que forman una UNIÓN no pueden contener una cláusula ORDER BY. La única cláusula ORDER BY permitida está al final de UNION y se aplica a toda la UNION, lo que hace que xxx UNION yyy ORDER BY zzzel equivalente sea(xxx UNION yyy) ORDER BY zzz
Nicholas Carey el
39

Para que el ordenamiento se aplique solo a la primera declaración en UNION, puede ponerlo en una subselección con UNION ALL (ambos parecen ser necesarios en Oracle):

Select id,name,age FROM 
(    
 Select id,name,age
 From Student
 Where age < 15
 Order by name
)
UNION ALL
Select id,name,age
From Student
Where Name like "%a%"

O (abordando el comentario de Nicholas Carey) puede garantizar que se ordena el SELECT superior y los resultados aparecen sobre el SELECT inferior de esta manera:

Select id,name,age, 1 as rowOrder
From Student
Where age < 15
UNION
Select id,name,age, 2 as rowOrder
From Student
Where Name like "%a%"
Order by rowOrder, name
BA TabNabber
fuente
44
Si. Eso ordena los resultados de la subselección. Eso NO ordena los resultados de la selectdeclaración que hace referencia a esa subselección. Según el estándar SQL, el orden de los resultados no está definido salvo una order bycláusula explícita . Lo primero selecten su ejemplo probablemente devuelva sus resultados en el orden devuelto por la subselección, pero no está garantizado. Además, eso * no * garantiza el orden del conjunto de resultados de la totalidad union(la misma regla en la Norma). Si depende del pedido, eventualmente será mordido.
Nicholas Carey
1
@Nicholas Carey: cuando probé inicialmente usando UNION, se comportaba de manera impredecible como lo describiste, creo que UNION ALL (al menos en Oracle) era necesario para ordenar el SELECT superior por encima del inferior. Sin embargo, he proporcionado una alternativa que garantiza un orden correcto y debe ser independiente de la base de datos.
BA TabNabber
No funciona para mi El que tiene UNION ALL todavía no puede mantener el orden dentro del primero SELECT.
Amit Chigadani
Y el problema con la segunda consulta es que no elimina los registros duplicados. Porque ha agregado otra columna 'rowOrder' que podría tener un valor diferente en los registros duplicados. El propósito de UNION contra UNION ALL se pierde.
Amit Chigadani
1
@AmitChigadani La eliminación de duplicados no era parte de la pregunta original, pero para hacerlo, las cláusulas WHERE se pueden modificar para garantizar la unicidad. por ejemplo: Donde Nombre como "% a%" Y edad> = 15
BA TabNabber
12

Las otras dos respuestas son correctas, pero pensé que valía la pena señalar que el lugar en el que me quedé atascado no era darse cuenta de que necesitarás ordenar por el alias y asegurarte de que el alias sea el mismo para ambas selecciones ... así que

select 'foo'
union
select item as `foo`
from myTable
order by `foo`

Tenga en cuenta que estoy usando comillas simples en la primera selección, pero con comillas para los demás.

Eso te dará la clasificación que necesitas.

Yevgeny Simkin
fuente
¿Qué es lo importante que quieres hacer con el uso de comillas simples en la primera selección y backticks en otra? Idealmente debería ser consistente.
nanosoft
La primera selección es un literal; es un encabezado como 'NOMBRES'. La segunda selección es una referencia a una tabla. Entonces su primera fila dirá "NOMBRES" y el resto de las filas serán los nombres reales seleccionados de la tabla. El punto es que su encabezado puede ser la misma cadena que el nombre de la columna de la que está seleccionando y esta es la solución para usar la etiqueta que desea sin que choque en su unión.
Yevgeny Simkin
2
Después de experimentar un poco, veo que el alias mencionado en la cláusula ORDER BY debe mencionarse en las cláusulas SELECT. No puedes ordenar por otra columna. Por supuesto, puede solucionarlo envolviendo todo en un SELECT a, b, c FROM (<insert union query here>) AS x;si realmente desea evitar devolver la columna adicional.
Wodin
11

Order Byse aplica después union, así que solo agregue una order bycláusula al final de las declaraciones:

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like '%a%'
Order By name
Sunil Kumar
fuente
9

Si quiero que el tipo se aplique solo a uno de UNION si uso Union all:

Select id,name,age
From Student
Where age < 15
Union all
Select id,name,age
From 
(
Select id,name,age
From Student
Where Name like "%a%"
Order by name
)
osydorchuk
fuente
8

Como se indicó en otras respuestas, 'Ordenar por' después de ÚLTIMA unión debe aplicarse a ambos conjuntos de datos unidos por la unión.

Estaba teniendo dos conjuntos de datos pero usando tablas diferentes pero las mismas columnas. 'Ordenar por' después de ÚLTIMA Unión todavía no funcionaba. El uso de ALIAS para la columna utilizada en 'ordenar por' hizo el truco.

Select Name, Address for Employee 
Union
Select Customer_Name, Address from Customer
order by customer_name;   --Won't work

Entonces, la solución es usar Alias ​​'User_Name':

Select Name as User_Name, Address for Employee 
Union
Select Customer_Name as User_Name, Address from Customer
order by User_Name; 
Mandrágora
fuente
-1

Puede usar esto:

Select id,name,age
From Student
Where age < 15
Union ALL
SELECT * FROM (Select id,name,age
From Student
Where Name like "%a%")
Ahmad Aghazadeh
fuente