Consulta SQL: uso de Order By en UNION

83

¿Cómo se puede ordenar mediante programación una consulta de unión al extraer datos de dos tablas? Por ejemplo,

SELECT table1.field1 FROM table1 ORDER BY table1.field1
UNION
SELECT table2.field1 FROM table2 ORDER BY table2.field1

Lanza una excepción

Nota: esto se está intentando en el motor de base de datos MS Access Jet

Curtis Inderwiesche
fuente

Respuestas:

118

A veces es necesario tener ORDER BYen cada una de las secciones con las que debe combinarse UNION.

En este caso

SELECT * FROM 
(
  SELECT table1.field1 FROM table1 ORDER BY table1.field1
) DUMMY_ALIAS1

UNION ALL

SELECT * FROM
( 
  SELECT table2.field1 FROM table2 ORDER BY table2.field1
) DUMMY_ALIAS2
ajgreyling
fuente
1
funcionó para mí cuando el orden afecta el conjunto de resultados (como cuando se usa Top x)
James Barrass
¡Esto es exactamente lo que estoy buscando! ¡Gracias!
Srichand Yella
Funciona muy bien para mí ... debes asegurarte de que la selección externa tenga un alias de tabla. Eso me mordió.
Troy
No tuve problemas para usar esta sintaxis con Microsoft SQL Server Standard (64 bits) versión 11.0.5058.0.
hlovdal
3
En SSMS, deberá cambiar las subconsultas a SELECT TOP 100 PERCENTpara poder usarlas ORDER BYen una
subconsulta
64
SELECT field1 FROM table1
UNION
SELECT field1 FROM table2
ORDER BY field1
Anne Porosoff
fuente
18
Esto técnicamente no logra lo que estaba preguntando lógicamente en la pregunta original.
Ian Boyd
2
@Ian Boyd: Entiendo su punto, pero lo que están pidiendo no tiene sentido lógico: ¡la unión opera en conjuntos y los conjuntos no tienen orden!
cuando
8
@onedaywhen El autor original quiere concatenar dos conjuntos ordenados de resultados. UNIONno permite que eso suceda. Puede haber otra construcción para hacerlo. Puede que no. De cualquier manera, esta respuesta no cumple técnicamente lo que el autor estaba preguntando.
Ian Boyd
4
@Ian Boyd: En SQL, ORDER BYes parte de un cursor, mientras que UNIONopera en tablas, por lo que su código no puede funcionar. No veo cómo se puede inferir la intención del OP a partir de un código absurdo. Considere que SQL UNIONelimina los duplicados: si estos son sus "conjuntos ordenados de resultados", {1, 2, 3} UNION {2, 4, 6}¿el resultado sería {1, 2, 3, 4, 6}o {1, 3, 2, 4, 6}? No lo sabemos porque la unión de "conjuntos ordenados de resultados" no está definida con respecto a SQL y el OP no lo ha especificado.
cuando
Estoy usando MYSQL, he incluido el campo (campo de pedido) en todas las declaraciones de selección. Luego, simplemente agregó Ordenar por al final, funciona bien para mí.
CreativeManix
57

Creo que esto explica muy bien.

La siguiente es una consulta UNION que usa una cláusula ORDER BY:

select supplier_id, supplier_name
from suppliers
where supplier_id > 2000
UNION
select company_id, company_name
from companies
where company_id > 1000
ORDER BY 2;

Dado que los nombres de las columnas son diferentes entre las dos instrucciones "select", es más ventajoso hacer referencia a las columnas en la cláusula ORDER BY por su posición en el conjunto de resultados.

En este ejemplo, hemos ordenado los resultados por supplier_name/ company_nameen orden ascendente, como se indica con "ORDER BY 2".

Los campos supplier_name/ company_nameestán en la posición # 2 en el conjunto de resultados.

Tomado de aquí: http://www.techonthenet.com/sql/union.php

Anson Smith
fuente
28

Usando un ejemplo concreto:

SELECT name FROM Folders ORDER BY name
UNION
SELECT name FROM Files ORDER BY name

Archivos:

name
=============================
RTS.exe
thiny1.etl
thing2.elt
f.txt
tcpdump_trial_license (1).zip

Carpetas:

name
============================
Contacts
Desktop
Downloads
Links
Favorites
My Documents

Resultado deseado: (resultados de la primera selección primero, es decir, carpetas primero)

Contacts
Desktop
Downloads
Favorites
Links
My Documents
f.txt
RTMS.exe
tcpdump_trial_license (1).zip
thiny1.etl
thing2.elt

SQL para lograr los resultados deseados:

SELECT name 
FROM (
    SELECT 1 AS rank, name FROM Folders
    UNION 
    SELECT 2 AS rank, name FROM Files) dt
ORDER BY rank, name
Ian Boyd
fuente
3
Esta es la mejor respuesta con diferencia
javier_domenech
1
¡Esta es una GRAN respuesta!
Ali Gonabadi
Nota: debe asignar un alias a la tabla derivada (como se muestra en este ejemplo con dt) o no funcionará. Esto me desconcertó por un tiempo, ya que había omitido ese detalle para empezar y el mensaje de error que arrojó SSMS no es particularmente útil.
CactusCake
17

Aquí hay un ejemplo de Northwind 2007:

SELECT [Product ID], [Order Date], [Company Name], [Transaction], [Quantity]
FROM [Product Orders]
UNION SELECT [Product ID], [Creation Date], [Company Name], [Transaction], [Quantity]
FROM [Product Purchases]
ORDER BY [Order Date] DESC;

La cláusula ORDER BY solo debe ser la última declaración, después de haber realizado toda la unión. Puede unir varios conjuntos, luego poner una cláusula ORDER BY después del último conjunto.

Precio de Todd
fuente
9
(SELECT table1.field1 FROM table1 
UNION
SELECT table2.field1 FROM table2) ORDER BY field1 

¿Trabajo? Recuerda pensar conjuntos. Obtenga el conjunto que desea usando una unión y luego realice sus operaciones en él.

Mella
fuente
También puede usar valores ordinales en su orden por cláusula en caso de que los campos que desea ordenar tengan un nombre diferente
Anson Smith
5
SELECT table1Column1 as col1,table1Column2 as col2
    FROM table1
UNION
(    SELECT table2Column1 as col1, table1Column2 as col2
         FROM table2
)
ORDER BY col1 ASC
JohnMcG
fuente
4
SELECT field1
FROM ( SELECT field1 FROM table1
       UNION
       SELECT field1 FROM table2
     ) AS TBL
ORDER BY TBL.field1

(use ALIAS)

MJ Latifi
fuente
@DisplacedGuy si MJ tiene una mejor respuesta a una pregunta que cualquiera de las anteriores, y en este caso la respuesta aceptada claramente tiene problemas, entonces MJ debería poder hacerlo y lo animo a dejar nuevas respuestas
MobileMon
Y por cierto, ¡la respuesta de MJ es la mejor! (al menos para mí)
MobileMon
4

Esta es la cosa más estúpida que he visto en mi vida, pero funciona y no se pueden discutir los resultados.

SELECT *
FROM (
    SELECT table1.field1 FROM table1 ORDER BY table1.field1
    UNION
    SELECT table2.field1 FROM table2 ORDER BY table2.field1
) derivedTable

El interior de la tabla derivada no se ejecutará por sí solo, pero como tabla derivada funciona perfectamente bien. Probé esto en SS 2000, SS 2005, SS 2008 R2 y los tres funcionan.

tlang
fuente
2

Asi es como se hace

select * from 
    (select top 100 percent pointx, pointy from point
     where pointtype = 1
     order by pointy) A
union all
select * from 
    (select top 100 percent pointx, pointy from point
     where pointtype = 2
     order by pointy desc) B
Prayut Parsekar
fuente
2

Al examinar esta sección de comentarios, me encontré con dos patrones diferentes que respondían a la pregunta. Lamentablemente, para SQL 2012, el segundo patrón no funciona, así que aquí está mi "solución alternativa"


Ordenar por en una columna común

Este es el caso más fácil que puede encontrar. Como señalaron muchos usuarios, todo lo que realmente necesita hacer es agregar un Order Byal final de la consulta

SELECT a FROM table1
UNION
SELECT a FROM table2
ORDER BY field1

o

SELECT a FROM table1 ORDER BY field1
UNION
SELECT a FROM table2 ORDER BY field1

Ordenar por en diferentes columnas

Aquí es donde realmente se vuelve complicado. Usando SQL 2012, probé la publicación superior y no funciona.

SELECT * FROM 
(
  SELECT table1.field1 FROM table1 ORDER BY table1.field1
) DUMMY_ALIAS1

UNION ALL

SELECT * FROM
( 
  SELECT table2.field1 FROM table2 ORDER BY table2.field1
) DUMMY_ALIAS2

Siguiendo la recomendación en el comentario probé esto

SELECT * FROM 
(
  SELECT TOP 100 PERCENT table1.field1 FROM table1 ORDER BY table1.field1
) DUMMY_ALIAS1

UNION ALL

SELECT * FROM
( 
  SELECT TOP 100 PERCENT table2.field1 FROM table2 ORDER BY table2.field1
) DUMMY_ALIAS2

Este código se compiló pero el DUMMY_ALIAS1y DUMMY_ALIAS2anuló lo Order Byestablecido en la Selectdeclaración que lo hace inutilizable.

La única solución que se me ocurrió, que funcionó para mí, fue no usar un sindicato y, en cambio, hacer que las consultas se ejecutaran individualmente y luego tratar con ellas. Básicamente, no usar un Unioncuando quierasOrder By

Esfera de burbujas
fuente
1

Al usar el orden por separado, cada subconjunto obtiene orden, pero no el conjunto completo, que es lo que desearía unir dos tablas.

Debería usar algo como esto para tener un conjunto ordenado:

SELECT TOP (100) PERCENT field1, field2, field3, field4, field5 FROM 
(SELECT table1.field1, table1.field2, table1.field3, table1.field4, table1.field5 FROM table1
UNION ALL 
SELECT table2.field1, table2.field2, table2.field3, table2.field4, table2.field5 FROM  table2) 
AS unitedTables ORDER BY field5 DESC
Ernesto Morales
fuente
0

La segunda tabla no puede incluir el nombre de la tabla en la ORDER BYcláusula.

Entonces...

SELECT table1.field1 FROM table1 ORDER BY table1.field1
UNION
SELECT table2.field1 FROM table2 ORDER BY field1

No lanza una excepción

Curtis Inderwiesche
fuente
Qué buena pregunta fue esta. ¿Puede decir si su versión, o la anidada, devuelve los resultados deseados? ¿O ambos devuelven los mismos resultados? Si es así, ¿la solución anidada (del otro tipo) sería más eficaz porque solo hace ORDENAR UNA vez?
DOK
No estoy seguro del beneficio de rendimiento en el motor Jet, pero diría que la legibilidad aumenta debido al anidamiento.
Curtis Inderwiesche
0

Si es necesario para mantener la clasificación interna:

SELECT 1 as type, field1 FROM table1 
UNION 
SELECT 2 as type, field1 FROM table2 
ORDER BY type, field1
usuario1795683
fuente
0
(SELECT FIELD1 AS NEWFIELD FROM TABLE1 ORDER BY FIELD1)
UNION
(SELECT FIELD2 FROM TABLE2 ORDER BY FIELD2)
UNION
(SELECT FIELD3 FROM TABLE3 ORDER BY FIELD3) ORDER BY NEWFIELD

Prueba esto. Funcionó para mí.

mandroide
fuente
0

Para Sql Server 2014/2012 / Otros (sin marcar):

SELECT * FROM 
(
  SELECT table1.field1 FROM table1 ORDER BY table1.field1
) 
as DUMMY_ALIAS1

UNION ALL

SELECT * FROM
( 
  SELECT table2.field1 FROM table2 ORDER BY table2.field1
) 
as DUMMY_ALIAS2
Bimal Das
fuente
Obtiene un error de compilación en 2012 al intentar este. La secuencia de comandos no funcionará para un procedimiento almacenado. Necesita la cláusula superior.
Timothy Dooling