Requête SQL - Utilisation de Order By dans UNION

83

Comment trier par programme une requête Union lors de l'extraction de données à partir de deux tables? Par exemple,

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

Lève une exception

Remarque: ceci est tenté sur le moteur de base de données MS Access Jet

Curtis Inderwiesche
la source

Réponses:

118

Parfois, vous devez avoir le ORDER BYdans chacune des sections qui doivent être combinées avec UNION.

Dans ce cas

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
la source
1
a fonctionné pour moi lorsque l'ordre par affecte le jeu de résultats (comme lors de l'utilisation de Top x)
James Barrass
C'est exactement ce que je recherche! Merci!
Srichand Yella
Fonctionne très bien pour moi ... vous devez vous assurer que la sélection externe a un alias de table. Cela m'a mordu.
Troy
Je n'ai eu aucun problème à utiliser cette syntaxe avec la version 11.0.5058.0 de Microsoft SQL Server Standard (64 bits).
hlovdal
3
Dans SSMS, vous devrez changer les sous-requêtes SELECT TOP 100 PERCENTen afin de les utiliser ORDER BYdans une sous-requête
Joseph Nields
64
SELECT field1 FROM table1
UNION
SELECT field1 FROM table2
ORDER BY field1
Anne Porosoff
la source
18
Cela n'accomplit pas techniquement ce que vous demandiez logiquement dans la question initiale.
Ian Boyd
2
@Ian Boyd: Je comprends votre point de vue mais ce qu'ils demandent n'a aucun sens logique: l'union opère sur des ensembles et les ensembles n'ont pas d'ordre!
jour du
8
@onedaywhen L'auteur original souhaite concaténer deux ensembles ordonnés de résultats. UNIONne permet pas que cela se produise. Il peut y avoir une autre construction pour le faire. Il se peut que non. Quoi qu'il en soit, cette réponse n'accomplit pas techniquement ce que l'auteur demandait.
Ian Boyd
4
@Ian Boyd: En SQL, ORDER BYfait partie d'un curseur, alors qu'il UNIONfonctionne sur des tables, donc leur code ne peut pas fonctionner. Je ne vois pas comment vous pouvez déduire l'intention du PO à partir d'un code absurde. Considérez que SQL UNIONsupprime les doublons: si ce sont vos «ensembles ordonnés de résultats» {1, 2, 3} UNION {2, 4, 6}, le résultat serait-il {1, 2, 3, 4, 6}ou {1, 3, 2, 4, 6}? Nous ne savons pas car l'union des "ensembles ordonnés de résultats" n'est pas définie en ce qui concerne SQL et l'OP ne l'a pas spécifié.
jour du
J'utilise MYSQL, j'ai inclus le champ (Champ de commande) dans toutes les instructions de sélection. Ensuite, juste ajouté Order by à la fin, fonctionne bien pour moi.
CreativeManix
57

Je pense que cela explique bien.

Voici une requête UNION qui utilise une clause 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;

Étant donné que les noms de colonne sont différents entre les deux instructions "select", il est plus avantageux de référencer les colonnes de la clause ORDER BY par leur position dans le jeu de résultats.

Dans cet exemple, nous avons trié les résultats par supplier_name/ company_namedans l'ordre croissant, comme indiqué par "ORDER BY 2".

Les champs supplier_name/ company_namesont en position n ° 2 dans le jeu de résultats.

Tiré d'ici: http://www.techonthenet.com/sql/union.php

Anson Smith
la source
28

En utilisant un exemple concret:

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

Des dossiers:

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

Dossiers:

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

Sortie souhaitée: (résultats de la première sélection en premier, c'est-à-dire les dossiers en premier)

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

SQL pour obtenir les résultats souhaités:

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
la source
3
C'est de loin la meilleure réponse
javier_domenech
1
C'est une excellente réponse!
Ali Gonabadi
Remarque - vous devez donner à la table dérivée un alias (comme indiqué dans cet exemple avec dt) ou cela ne fonctionnera pas. J'ai été perplexe pendant un moment car j'avais omis ce détail pour commencer et le message d'erreur généré par SSMS n'est pas particulièrement utile.
CactusCake
17

Voici un exemple 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 clause ORDER BY doit juste être la dernière instruction, une fois que vous avez terminé votre union. Vous pouvez unir plusieurs ensembles ensemble, puis mettre une clause ORDER BY après le dernier ensemble.

Prix ​​Todd
la source
9
(SELECT table1.field1 FROM table1 
UNION
SELECT table2.field1 FROM table2) ORDER BY field1 

Travail? N'oubliez pas de penser ensembles. Obtenez l'ensemble souhaité à l'aide d'une union, puis effectuez vos opérations dessus.

pseudo
la source
Vous pouvez également utiliser des valeurs ordinales dans votre commande par clause dans le cas où les champs que vous souhaitez trier sur sont nommés différemment
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
la source
4
SELECT field1
FROM ( SELECT field1 FROM table1
       UNION
       SELECT field1 FROM table2
     ) AS TBL
ORDER BY TBL.field1

(utilisez ALIAS)

MJ Latifi
la source
@DisplacedGuy si MJ a une meilleure réponse à une question, alors n'importe laquelle des réponses ci-dessus, et dans ce cas, la réponse acceptée a clairement des problèmes, alors MJ devrait pouvoir et je l'encourage à laisser de nouvelles réponses
MobileMon
Et d'ailleurs, la réponse de MJ est la meilleure! (pour moi au moins)
MobileMon
4

C'est la chose la plus stupide que j'aie jamais vue, mais cela fonctionne et vous ne pouvez pas discuter des résultats.

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

L'intérieur de la table dérivée ne s'exécutera pas tout seul, mais comme une table dérivée fonctionne parfaitement bien. J'ai essayé ceci sur SS 2000, SS 2005, SS 2008 R2 et les trois fonctionnent.

tlang
la source
2

C'est comme ça que ça se fait

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
la source
2

En parcourant cette section de commentaires, je suis tombé sur deux modèles différents répondant à la question. Malheureusement pour SQL 2012, le deuxième modèle ne fonctionne pas, voici donc mon «travail»


Trier par sur une colonne commune

C'est le cas le plus simple que vous puissiez rencontrer. Comme de nombreux utilisateurs l'ont souligné, tout ce que vous avez à faire est d'ajouter un Order Byà la fin de la requête

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

ou

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

Trier par sur différentes colonnes

C'est là que ça devient compliqué. En utilisant SQL 2012, j'ai essayé le premier article et cela ne fonctionne pas.

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

Suite à la recommandation dans le commentaire, j'ai essayé ceci

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

Ce code a bien compilé mais le DUMMY_ALIAS1et DUMMY_ALIAS2écrasé le Order Byétabli dans l' Selectinstruction qui le rend inutilisable.

La seule solution à laquelle je pouvais penser, qui fonctionnait pour moi, était de ne pas utiliser de syndicat, mais plutôt de faire exécuter les requêtes individuellement et de les traiter ensuite. Donc, en gros, ne pas utiliser un Unionquand vous le souhaitezOrder By

Bubblesphère
la source
1

En utilisant order séparément, chaque sous-ensemble obtient de l'ordre, mais pas l'ensemble complet, ce que vous souhaiteriez pour unir deux tables.

Vous devriez utiliser quelque chose comme ceci pour avoir un ensemble ordonné:

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
la source
0

La deuxième table ne peut pas inclure le nom de la table dans la ORDER BYclause.

Donc...

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

Ne lève pas d'exception

Curtis Inderwiesche
la source
Quelle bonne question c'était. Pouvez-vous dire si votre version, ou celle imbriquée, renvoie les résultats souhaités? Ou renvoient-ils tous les deux les mêmes résultats? Si tel est le cas, la solution imbriquée (de l'autre type) serait-elle plus performante car elle ne ORDER BY qu'une seule fois?
DOK
Je ne suis pas sûr de l'avantage des performances sur le moteur Jet, mais je dirais que la lisibilité est augmentée en raison de l'emboîtement.
Curtis Inderwiesche
0

Si nécessaire pour conserver le tri intérieur:

SELECT 1 as type, field1 FROM table1 
UNION 
SELECT 2 as type, field1 FROM table2 
ORDER BY type, field1
user1795683
la source
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

Essaye ça. Cela a fonctionné pour moi.

mandroïde
la source
0

Pour Sql Server 2014/2012 / Autres (non vérifié):

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
la source
Vous obtenez une erreur de compilation en 2012 en essayant celui-ci. Le script ne fonctionnera pas pour une procédure stockée. Vous avez besoin de la clause supérieure.
Timothy Dooling le