Wie bestelle ich mit union in SQL?


201

Ist es möglich zu bestellen, wenn die Daten von vielen stammen, die sie auswählen und zusammenführen? Sowie

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

Wie kann ich diese Abfrage nach Namen bestellen?

Einige sagten, Sie können so abfragen.

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

Aber in diesem Fall ignoriere ich diese Lösung einfach.


1
Wenn Sie dieselbe Spalte in der Union-Abfrage haben, geben Sie am Ende die Reihenfolge nach Ihrem Spaltennamen ein.
Anirban Karak

Antworten:


266

Einfach schreiben

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

Die Reihenfolge bis wird auf die gesamte Ergebnismenge angewendet


45
Was ist, wenn ich möchte, dass die Sorte nur auf die oberste der UNION angewendet wird?
Marifrahman

7
@ Marifrahman siehe meine Antwort stackoverflow.com/a/43855496/2340825
BA TabNabber

2
@marifrahman tut mir leid, ein altes Thema zu graben, aber es kann anderen helfen. Wenn Sie möchten, dass ORDER BY auf den ersten Teil der UNION angewendet wird, schützen Sie dieses SELECT in Klammern.
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

46
Wie bernd_k hervorhob, dürfen die einzelnen SELECTs, aus denen eine UNION besteht, per Definition keine ORDER BY-Klausel enthalten. Die einzige ORDER BY-Klausel, die zulässig ist, befindet sich am Ende der UNION und gilt für die gesamte UNION, was xxx UNION yyy ORDER BY zzzdas Äquivalent von(xxx UNION yyy) ORDER BY zzz
Nicholas Carey am

39

Damit die Sortierung nur auf die erste Anweisung in der UNION angewendet wird, können Sie sie mit UNION ALL in eine Unterauswahl einfügen (beide scheinen in Oracle erforderlich zu sein):

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%"

Oder (unter Berücksichtigung des Kommentars von Nicholas Carey) Sie können garantieren, dass das obere SELECT bestellt ist und die Ergebnisse wie folgt über dem unteren SELECT angezeigt werden:

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

4
Ja. Das ordnet die Ergebnisse der Unterauswahl. Das ordnet die Ergebnisse der selectAnweisung, die auf diese Unterauswahl verweist, NICHT an . Gemäß dem SQL-Standard ist die Reihenfolge der Ergebnisse undefiniert, mit Ausnahme einer expliziten order byKlausel. Das erste selectin Ihrem Beispiel gibt wahrscheinlich die Ergebnisse in der von der Unterauswahl zurückgegebenen Reihenfolge zurück, ist jedoch nicht garantiert. Darüber hinaus garantiert dies nicht die Reihenfolge der Ergebnismenge der gesamten union(gleiche Regel im Standard). Wenn Sie von der Bestellung abhängig sind, werden Sie - irgendwann - gebissen.
Nicholas Carey

1
@Nicholas Carey - Als ich anfänglich mit einer UNION getestet habe, hat es sich unvorhersehbar verhalten, wie Sie es beschrieben haben. Ich denke, die UNION ALL (zumindest in Oracle) war notwendig, um das obere SELECT über dem unteren zu bestellen. Ich habe jedoch eine Alternative bereitgestellt, die eine korrekte Bestellung garantiert und datenbankunabhängig sein sollte.
BA TabNabber

Ich arbeite nicht für mich. Der mit UNION ALL kann die Reihenfolge innerhalb der ersten noch nicht aufrechterhalten SELECT.
Amit Chigadani

Das Problem bei der zweiten Abfrage besteht darin, dass die doppelten Datensätze nicht entfernt werden. Weil Sie eine weitere Spalte 'rowOrder' hinzugefügt haben, die möglicherweise einen anderen Wert für die doppelten Datensätze hat. Zweck der UNION gegen UNION ALL ist verloren.
Amit Chigadani

1
@AmitChigadani Die Beseitigung von Duplikaten war nicht Teil der ursprünglichen Frage, aber dazu können die WHERE-Klauseln geändert werden, um die Eindeutigkeit sicherzustellen. Beispiel: Wobei Name wie "% a%" UND Alter> = 15
BA TabNabber

12

Die beiden anderen Antworten sind richtig, aber ich fand es erwähnenswert, dass der Ort, an dem ich feststeckte, nicht realisierte, dass Sie eine Reihenfolge nach dem Alias ​​benötigen und sicherstellen müssen, dass der Alias ​​für beide Auswahlen gleich ist ... also

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

Beachten Sie, dass ich in der ersten Auswahl einfache Anführungszeichen verwende, für die anderen jedoch Backticks.

So erhalten Sie die Sortierung, die Sie benötigen.


Was ist wichtig für die Verwendung von einfachen Anführungszeichen in der ersten Auswahl und Backticks in anderen? Idealerweise sollte es konsistent sein.
Nanosoft

Die erste Auswahl ist ein Literal; Es ist ein Header wie 'NAMES'. Die zweite Auswahl ist eine Referenz auf eine Tabelle. Ihre erste Zeile sagt also "NAMES" und der Rest der Zeilen sind die tatsächlichen Namen, die aus der Tabelle ausgewählt wurden. Der Punkt ist, dass Ihre Kopfzeile möglicherweise dieselbe Zeichenfolge wie der Name der Spalte hat, aus der Sie auswählen, und dies ist die Lösung für die Verwendung der gewünschten Beschriftung, ohne dass diese in Ihrer Union kollidiert.
Jewgeni Simkin

2
Nach einigen Experimenten sehe ich, dass der in der ORDER BY-Klausel erwähnte Alias ​​in den SELECT-Klauseln erwähnt werden muss. Sie können nicht nach einer anderen Spalte sortieren. Natürlich können SELECT a, b, c FROM (<insert union query here>) AS x;Sie das umgehen , indem Sie das Ganze in eine einschließen, wenn Sie wirklich vermeiden möchten, die zusätzliche Spalte zurückzugeben.
Wodin

11

Order Bywird nach angewendet union, fügen Sie einfach eine order byKlausel am Ende der Anweisungen hinzu:

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

9

Wenn ich möchte, dass die Sorte nur auf eine der UNION angewendet wird, wenn Union all verwendet wird:

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
)

8

Wie in anderen Antworten angegeben, sollte "Order by" nach LAST Union für beide Datensätze gelten, die durch union verbunden sind.

Ich hatte zwei Datensätze, verwendete aber unterschiedliche Tabellen, aber dieselben Spalten. 'Order by' nachdem LAST Union nicht mehr funktioniert hat. Die Verwendung von ALIAS für die in 'order by' verwendete Spalte hat den Trick getan.

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

Die Lösung lautet also 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; 

-1

Kann dies verwenden:

Select id,name,age
From Student
Where age < 15
Union ALL
SELECT * FROM (Select id,name,age
From Student
Where Name like "%a%")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.