Bagaimana cara memesan dengan bergabung dalam SQL?

202

Apakah mungkin untuk memesan ketika data berasal dari banyak pilih dan menyatukannya bersama? Seperti

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

Bagaimana saya bisa memesan permintaan ini dengan nama.

Beberapa mengatakan Anda dapat meminta tampilan seperti ini.

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

Tetapi dalam hal ini saya mengabaikan solusi itu.

Guilgamo
sumber
1
Jika Anda memiliki kolom yang sama dalam kueri gabungan maka pada akhirnya masukkan nama kolom Anda.
anirban karak

Jawaban:

266

Cukup tulis

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

urutan oleh diterapkan ke resultset lengkap

bernd_k
sumber
45
Bagaimana jika saya ingin jenis diterapkan hanya pada bagian atas UNION?
marifrahman
7
@marifrahman lihat jawaban saya stackoverflow.com/a/43855496/2340825
BA TabNabber
2
@marifrahman menyesal menggali topik lama, tetapi mungkin membantu orang lain. Jika Anda ingin ORDER BY diterapkan pada bagian pertama UNION, lindungi SELECT ini dengan tanda kurung.
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
sumber
46
Seperti yang ditunjukkan oleh bernd_k, menurut definisi, masing-masing SELECT yang membentuk UNION tidak boleh mengandung klausa ORDER BY. Satu-satunya klausa ORDER BY yang diizinkan adalah pada akhir UNION dan itu berlaku untuk seluruh UNION, membuat xxx UNION yyy ORDER BY zzzpersamaan(xxx UNION yyy) ORDER BY zzz
Nicholas Carey
39

Agar penyortiran hanya berlaku untuk pernyataan pertama di UNION, Anda dapat memasukkannya ke dalam subselect dengan UNION ALL (keduanya tampaknya diperlukan di 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%"

Atau (menanggapi komentar Nicholas Carey) Anda dapat menjamin SELECT atas dipesan dan hasilnya muncul di atas SELECT bawah seperti ini:

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
sumber
4
Iya. Itu memerintahkan hasil dari subselect. Itu TIDAK memerintahkan hasil selectpernyataan yang merujuk subselect itu. Per Standar SQL, urutan hasil tidak ditentukan kecuali order byklausa eksplisit . Yang pertama selectdalam contoh Anda mungkin mengembalikan hasilnya dalam urutan yang dikembalikan oleh subselect, tetapi tidak dijamin. Lebih lanjut, itu * tidak * menjamin pemesanan set hasil keseluruhan union(aturan yang sama dalam Standar). Jika Anda bergantung pada urutannya, Anda akan - pada akhirnya - digigit.
Nicholas Carey
1
@ Nicolas Carey - ketika saya awalnya diuji menggunakan UNION itu berperilaku tak terduga seperti yang Anda jelaskan, saya pikir UNION ALL (setidaknya di Oracle) diperlukan untuk memesan SELECT atas di atas bagian bawah. Namun saya telah memberikan alternatif yang tidak menjamin pemesanan yang benar dan harus independen dari basis data.
BA TabNabber
Tidak bekerja untukku. Yang dengan UNION ALL masih gagal mempertahankan urutan dalam yang pertama SELECT.
Amit Chigadani
Dan masalah dengan permintaan kedua adalah, itu tidak menghilangkan catatan duplikat. Karena Anda telah menambahkan kolom lain 'rowOrder' yang mungkin memiliki nilai berbeda terhadap catatan duplikat. Tujuan UNION melawan UNION SEMUA hilang.
Amit Chigadani
1
@AmitChigadani Penghapusan duplikat bukan bagian dari pertanyaan asli, tetapi untuk melakukannya klausa WHERE dapat dimodifikasi untuk memastikan keunikan. misalnya: Di mana Nama seperti "% a%" DAN usia> = 15
BA TabNabber
12

Kedua jawaban lainnya benar, tetapi saya pikir perlu dicatat bahwa tempat saya macet tidak menyadari bahwa Anda akan perlu memesan oleh alias dan memastikan bahwa alias sama untuk kedua pilihan ... jadi

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

perhatikan bahwa saya menggunakan tanda kutip tunggal di pilih pertama tetapi backticks untuk yang lain.

Itu akan membuat Anda menyortir yang Anda butuhkan.

Yevgeny Simkin
sumber
apa yang penting yang ingin Anda buat dengan menggunakan satu kutipan di pilih pertama dan backticks di lainnya Idealnya harus konsisten.
nanosoft
Pilihan pertama adalah literal; itu adalah header seperti 'NAMES'. Pilihan kedua adalah referensi ke tabel. Jadi baris pertama Anda akan mengatakan "NAMES" dan sisa baris akan menjadi nama sebenarnya yang dipilih dari tabel. Intinya adalah bahwa tajuk Anda mungkin string yang sama dengan nama kolom yang Anda pilih dan ini adalah solusi untuk menggunakan label yang Anda inginkan tanpa bertabrakan di serikat Anda.
Yevgeny Simkin
2
Setelah beberapa percobaan saya melihat bahwa alias yang disebutkan dalam klausa ORDER BY harus disebutkan dalam klausa SELECT. Anda tidak dapat mengurutkan berdasarkan kolom lain. Tentu saja Anda dapat menyiasatinya dengan membungkus semuanya SELECT a, b, c FROM (<insert union query here>) AS x;jika Anda benar-benar ingin menghindari mengembalikan kolom tambahan.
Wodin
11

Order Byditerapkan setelah union, jadi tambahkan saja order byklausa di akhir pernyataan:

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
sumber
9

Jika saya ingin jenis diterapkan hanya pada satu UNION jika menggunakan 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
sumber
8

Seperti jawaban lain yang dinyatakan, 'Pesanan oleh' setelah LAST Union harus berlaku untuk kedua set data yang bergabung dengan serikat pekerja.

Saya memiliki dua set data tetapi menggunakan tabel yang berbeda tetapi kolom yang sama. 'Pesan oleh' setelah LAST Union masih tidak berfungsi. Menggunakan ALIAS untuk kolom yang digunakan dalam 'urutan oleh' melakukan trik.

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

Jadi solusinya gunakan 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; 
Mandrake
sumber
-1

Dapat menggunakan ini:

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
sumber