Làm thế nào để đặt hàng bằng cách kết hợp trong SQL?


201

Có thể đặt hàng khi dữ liệu đến từ nhiều lựa chọn và kết hợp nó lại với nhau không? Nhu la

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

Làm thế nào tôi có thể đặt truy vấn này theo tên.

Một số người nói bạn có thể truy vấn như thế này.

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

Nhưng trong trường hợp này tôi chỉ bỏ qua giải pháp đó.


1
Nếu bạn có cùng một cột trong truy vấn hợp nhất thì cuối cùng hãy đặt thứ tự theo tên cột của bạn.
karir anirban

Câu trả lời:


266

Chỉ viết

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

thứ tự được áp dụng cho tập kết quả hoàn chỉnh


45
Điều gì xảy ra nếu tôi muốn loại này chỉ được áp dụng trên một trong những UNION hàng đầu?
marifrahman

7
@marifrahman xem câu trả lời của tôi stackoverflow.com/a/43855496/2340825
BA TabNabber

2
@marifrahman xin lỗi để đào một chủ đề cũ, nhưng nó có thể giúp đỡ người khác. Trong trường hợp bạn muốn ORTER BY được áp dụng cho phần đầu tiên của UNION, hãy bảo vệ CHỌN này bằng dấu ngoặc đơn.
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
Như bernd_k đã chỉ ra, theo định nghĩa, các CHỌN riêng lẻ tạo thành UNION không được phép chứa mệnh đề ORDER BY. Mệnh đề ORDER BY duy nhất được phép là vào cuối UNION và nó được áp dụng cho toàn bộ UNION, làm cho xxx UNION yyy ORDER BY zzzhiệu quả của(xxx UNION yyy) ORDER BY zzz
Nicholas Carey

39

Để thực hiện sắp xếp chỉ áp dụng cho câu lệnh đầu tiên trong UNION, bạn có thể đặt nó trong phần phụ với UNION ALL (cả hai điều này dường như là cần thiết trong 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%"

Hoặc (giải quyết nhận xét của Nicholas Carey), bạn có thể đảm bảo CHỌN hàng đầu được đặt hàng và kết quả xuất hiện phía trên CHỌN phía dưới như thế này:

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
Đúng. Đó là thứ tự các kết quả của subselect. Điều đó KHÔNG yêu cầu kết quả của selecttuyên bố tham chiếu mà chọn. Theo Tiêu chuẩn SQL, thứ tự kết quả là không xác định, chặn một order bymệnh đề rõ ràng . Điều đó đầu tiên selecttrong ví dụ của bạn có thể trả về kết quả của nó theo thứ tự được trả về bởi subselect, nhưng nó không được bảo đảm. Hơn nữa, điều đó * không * đảm bảo thứ tự của tập kết quả của toàn bộ union(cùng quy tắc trong Tiêu chuẩn). Nếu bạn phụ thuộc vào thứ tự, cuối cùng - bạn sẽ bị cắn.
Nicholas Carey

1
@Nicholas Carey - khi tôi thử nghiệm lần đầu bằng cách sử dụng UNION, nó hoạt động không thể đoán trước như bạn mô tả, tôi nghĩ rằng UNION ALL (ít nhất là trong Oracle) là cần thiết để đặt hàng CHỌN trên cùng phía dưới. Tuy nhiên, tôi đã cung cấp một giải pháp thay thế đảm bảo thứ tự chính xác và phải độc lập với cơ sở dữ liệu.
BA TabNabber

Không làm việc cho tôi. Người có UNION ALL vẫn không duy trì trật tự trong lần đầu tiên SELECT.
Amit Chigadani

Và vấn đề với truy vấn thứ hai là, nó không loại bỏ các bản ghi trùng lặp. Bởi vì bạn đã thêm một cột khác 'rowOrder' có thể có giá trị khác với các bản ghi trùng lặp. Mục đích của UNION chống lại UNION ALL bị mất.
Amit Chigadani

1
@AmitChigadani Loại bỏ các bản sao không phải là một phần của câu hỏi ban đầu, nhưng để làm như vậy, các mệnh đề WHERE có thể được sửa đổi để đảm bảo tính duy nhất. ví dụ: Trường hợp Tên như "% a%" VÀ tuổi> = 15
BA TabNabber

12

Cả hai câu trả lời khác đều đúng, nhưng tôi nghĩ rằng đáng chú ý rằng nơi tôi bị mắc kẹt không nhận ra rằng bạn sẽ cần đặt hàng theo bí danh và đảm bảo rằng bí danh giống nhau cho cả hai lựa chọn ... vì vậy

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

lưu ý rằng tôi đang sử dụng các trích dẫn đơn trong lựa chọn đầu tiên nhưng backticks cho các dấu ngoặc kép khác.

Điều đó sẽ giúp bạn sắp xếp bạn cần.


điều quan trọng bạn muốn thực hiện bằng cách sử dụng trích dẫn đơn trong lần chọn đầu tiên và backticks khác là gì? Lý tưởng nhất là phải nhất quán.
nanosoft

Lựa chọn đầu tiên là một nghĩa đen; đó là một tiêu đề như 'TÊN'. Lựa chọn thứ hai là một tham chiếu đến một bảng. Vì vậy, hàng đầu tiên của bạn sẽ nói "TÊN" và các hàng còn lại sẽ là tên thực tế được chọn từ bảng. Vấn đề là tiêu đề của bạn rất có thể là cùng một chuỗi với tên của cột mà bạn đang chọn và đây là giải pháp để sử dụng nhãn bạn muốn mà không bị va chạm trong liên kết của bạn.
Yevgeny Simkin

2
Sau một số thử nghiệm tôi thấy rằng bí danh được đề cập trong mệnh đề ORDER BY phải được đề cập trong các mệnh đề CHỌN. Bạn không thể sắp xếp theo cột khác. Tất nhiên bạn có thể giải quyết vấn đề đó bằng cách gói toàn bộ thứ SELECT a, b, c FROM (<insert union query here>) AS x;nếu bạn thực sự muốn tránh trả lại cột phụ.
Wodin

11

Order Byđược áp dụng sau union, vì vậy chỉ cần thêm một order bymệnh đề vào cuối các câu lệnh:

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

9

Nếu tôi muốn loại này chỉ được áp dụng cho một trong UNION nếu sử dụng tất cả Liên minh:

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

Như các câu trả lời khác đã nêu, 'Sắp xếp theo' sau LAST Union nên áp dụng cho cả hai tập dữ liệu được nối bởi liên minh.

Tôi đã có hai bộ dữ liệu nhưng sử dụng các bảng khác nhau nhưng cùng một cột. 'Đặt hàng trước' sau khi LAST Union vẫn không hoạt động. Sử dụng ALIAS cho cột được sử dụng theo 'order by' đã thực hiện thủ thuật.

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

Vì vậy, giải pháp là sử dụng Bí danh '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

Có thể sử dụng cái này:

Select id,name,age
From Student
Where age < 15
Union ALL
SELECT * FROM (Select id,name,age
From Student
Where Name like "%a%")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.