Zapytanie SQL - użycie Order By w UNION


83

W jaki sposób można programowo posortować zapytanie składające podczas pobierania danych z dwóch tabel? Na przykład,

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

Zgłasza wyjątek

Uwaga: próbowano tego dokonać na silniku bazy danych MS Access Jet

Odpowiedzi:


118

Czasami trzeba mieć ORDER BYw każdej sekcji, z którą należy połączyć UNION.

W tym przypadku

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

1
zadziałało dla mnie, gdy kolejność wpływa na zestaw wyników (jak przy użyciu Top x)
James Barrass

Właśnie tego szukam! Dzięki!
Srichand Yella,

U mnie działa świetnie ... musisz się upewnić, że zewnętrzny wybór ma alias tabeli. To mnie ugryzło.
Troy

Nie miałem problemów z używaniem tej składni w Microsoft SQL Server Standard (64-bit) w wersji 11.0.5058.0.
hlovdal

3
W SSMS będziesz musiał zmienić SELECT TOP 100 PERCENTORDER BY
podzapytania

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

18
To technicznie nie spełnia tego, o co logicznie pytałeś w pierwotnym pytaniu.
Ian Boyd,

2
@Ian Boyd: Rozumiem, ale to, o co proszą, nie ma logicznego sensu: związek działa na zbiorach, a zbiory nie mają porządku!
kiedy

8
@onedaywhen Oryginalny autor chce połączyć dwa uporządkowane zestawy wyników. UNIONnie pozwala na to. Może istnieć inna konstrukcja, która to zrobi. Nie może. Tak czy inaczej, ta odpowiedź technicznie nie spełnia tego, o co prosił autor.
Ian Boyd,

4
@Ian Boyd: W SQL ORDER BYjest częścią kursora, podczas gdy UNIONoperuje na tabelach, dlatego ich kod nie może działać. Nie rozumiem, jak można wywnioskować zamiar OP na podstawie absurdalnego kodu. Weź pod uwagę, że SQL UNIONusuwa duplikaty: czy jeśli są to twoje „uporządkowane zestawy wyników”, {1, 2, 3} UNION {2, 4, 6}czy wynik byłby {1, 2, 3, 4, 6}czy {1, 3, 2, 4, 6}? Nie wiemy, ponieważ suma „uporządkowanych zestawów wyników” jest niezdefiniowana w przypadku SQL, a OP nie została określona.
onedaywhen

Używam MYSQL, zawarłem pole (pole zamówienia) we wszystkich instrukcjach wyboru. Następnie po prostu dodałem Zamów do na końcu, Działa dobrze dla mnie.
CreativeManix

57

Myślę, że to dobrze wyjaśnia.

Poniżej znajduje się zapytanie UNION, które używa klauzuli 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;

Ponieważ nazwy kolumn w obu instrukcjach „select” są różne, korzystniejsze jest odwoływanie się do kolumn w klauzuli ORDER BY na podstawie ich pozycji w zestawie wyników.

W tym przykładzie posortowaliśmy wyniki według supplier_name/ company_namew porządku rosnącym, zgodnie z oznaczeniem „ORDER BY 2”.

W supplier_name/ company_namepola są na pozycji # 2 w zestawie wyników.

Zaczerpnięte stąd: http://www.techonthenet.com/sql/union.php


28

Na konkretnym przykładzie:

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

Akta:

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

Lornetka składana:

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

Żądany wynik: (wyniki pierwszego wyboru jako pierwsze, tj. Najpierw foldery)

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

SQL, aby osiągnąć pożądane wyniki:

SELECT name 
FROM (
    SELECT 1 AS rank, name FROM Folders
    UNION 
    SELECT 2 AS rank, name FROM Files) dt
ORDER BY rank, name

3
To zdecydowanie najlepsza odpowiedź
javier_domenech

1
To świetna odpowiedź!
Ali Gonabadi

Uwaga - musisz nadać tabeli pochodnej alias (jak pokazano w tym przykładzie z dt), inaczej nie zadziała. Byłem tym zaskoczony przez chwilę, ponieważ na początku pominąłem ten szczegół, a komunikat o błędzie wyrzucony przez SSMS nie jest szczególnie pomocny.
CactusCake

17

Oto przykład z 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;

Klauzula ORDER BY musi być tylko ostatnią instrukcją, po wykonaniu wszystkich połączeń. Możesz połączyć kilka zestawów razem, a następnie umieścić klauzulę ORDER BY po ostatnim zestawie.


9
(SELECT table1.field1 FROM table1 
UNION
SELECT table2.field1 FROM table2) ORDER BY field1 

Praca? Pamiętaj o zestawach myślowych. Pobierz zestaw, który chcesz, używając unii, a następnie wykonaj na nim operacje.


Możesz również użyć wartości porządkowych w klauzuli order by na wypadek, gdyby pola, według których chcesz sortować, mają inne nazwy
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

4
SELECT field1
FROM ( SELECT field1 FROM table1
       UNION
       SELECT field1 FROM table2
     ) AS TBL
ORDER BY TBL.field1

(użyj ALIAS)


@DisplacedGuy jeśli MJ ma lepszą odpowiedź na pytanie, to którekolwiek z powyższych, aw tym przypadku zaakceptowana odpowiedź wyraźnie ma problemy, to MJ powinien być w stanie i zachęcam go do pozostawienia nowych odpowiedzi
MobileMon 20.11.2013 o

A tak przy okazji, odpowiedź MJ jest najlepsza! (przynajmniej dla mnie)
MobileMon

4

To najgłupsza rzecz, jaką kiedykolwiek widziałem, ale działa i nie można dyskutować z wynikami.

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

Wnętrze tabeli pochodnej nie będzie działać samodzielnie, ale jako tabela pochodna działa doskonale. Wypróbowałem to na SS 2000, SS 2005, SS 2008 R2 i wszystkie trzy działają.


2

Tak to się robi

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

2

Przeglądając tę ​​sekcję komentarzy, natrafiłem na dwa różne wzorce odpowiadające na to pytanie. Niestety w przypadku SQL 2012 drugi wzorzec nie działa, więc oto moje „obejście”


Zamów na wspólnej kolumnie

To najłatwiejszy przypadek, jaki możesz napotkać. Jak zauważyło wielu użytkowników, wszystko, co naprawdę musisz zrobić, to dodać Order Byna końcu zapytania

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

lub

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

Sortuj według w różnych kolumnach

Oto, gdzie to naprawdę staje się trudne. Używając SQL 2012, wypróbowałem najwyższy post i to nie działa.

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

Postępując zgodnie z zaleceniem w komentarzu, spróbowałem tego

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

Ten kod skompilował, ale DUMMY_ALIAS1i DUMMY_ALIAS2przesłania Order Byustalone w Selectinstrukcji, co sprawia, że ​​jest bezużyteczny.

Jedynym rozwiązaniem, które przyszło mi do głowy, które zadziałało dla mnie, było nie używanie unii, a zamiast tego wykonywanie zapytań indywidualnie, a następnie zajmowanie się nimi. Zasadniczo więc nie używaj a, Unionkiedy chceszOrder By


1

Używając kolejności osobno, każdy podzbiór uzyskuje porządek, ale nie cały zestaw, co chciałbyś połączyć dwa stoły.

Powinieneś użyć czegoś takiego, aby mieć jeden zamówiony zestaw:

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

0

Druga tabela nie może zawierać nazwy tabeli w ORDER BYklauzuli.

Więc...

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

Nie zgłasza wyjątku


Cóż to było za dobre pytanie. Czy możesz stwierdzić, czy Twoja wersja, czy wersja zagnieżdżona, zwraca pożądane wyniki? A może oba zwracają te same wyniki? Jeśli tak, to czy zagnieżdżone rozwiązanie (innego gościa) byłoby bardziej wydajne, ponieważ wykonuje polecenie ORDER BY tylko raz?
DOK

Nie jestem pewien, czy wydajność silnika Jet wpływa korzystnie na wydajność, ale powiedziałbym, że dzięki zagnieżdżeniu zwiększa się czytelność.
Curtis Inderwiesche,

0

Jeśli to konieczne, aby zachować sortowanie wewnętrzne:

SELECT 1 as type, field1 FROM table1 
UNION 
SELECT 2 as type, field1 FROM table2 
ORDER BY type, field1

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

Spróbuj tego. U mnie to zadziałało.


0

Dla Sql Server 2014/2012 / Inne (nie zaznaczone):

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

Otrzymujesz błąd kompilacji w 2012 roku, próbując tego. Skrypt nie będzie działał dla procedury składowanej. Potrzebujesz najwyższej klauzuli.
Timothy Dooling
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.