Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Cách sử dụng ORDER BY bên trong UNION

Một cái gì đó như thế này sẽ hoạt động trong MySQL:

SELECT a.*
  FROM ( 
         SELECT ...  FROM ... ORDER BY ... 
       ) a
 UNION ALL 
SELECT b.*
  FROM ( 
         SELECT ...  FROM ... ORDER BY ... 
       ) b

để trả về các hàng theo thứ tự mà chúng tôi muốn chúng được trả lại. tức là MySQL dường như tôn trọng ORDER BY mệnh đề bên trong dạng xem nội tuyến.

Tuy nhiên, không có ORDER BY mệnh đề trên truy vấn ngoài cùng, thứ tự các hàng được trả về là không đảm bảo.

Nếu chúng ta cần các hàng được trả về trong một trình tự cụ thể, chúng ta có thể bao gồm ORDER BY trên truy vấn ngoài cùng. Trong nhiều trường hợp sử dụng, chúng ta chỉ có thể sử dụng ORDER BY trên truy vấn ngoài cùng để đáp ứng kết quả.

Nhưng khi chúng ta gặp trường hợp sử dụng trong đó chúng ta cần tất cả các hàng từ truy vấn đầu tiên được trả về trước tất cả các hàng từ truy vấn thứ hai, một tùy chọn là bao gồm một cột phân biệt bổ sung trong mỗi truy vấn. Ví dụ:thêm ,'a' AS src trong truy vấn đầu tiên, ,'b' AS src đến truy vấn thứ hai.

Sau đó, truy vấn ngoài cùng có thể bao gồm ORDER BY src, name , để đảm bảo chuỗi kết quả.

THEO DÕI

Trong truy vấn ban đầu của bạn, ORDER BY trong các truy vấn của bạn bị loại bỏ bởi trình tối ưu hóa; vì không có ORDER BY được áp dụng cho truy vấn bên ngoài, MySQL có thể tự do trả về các hàng theo bất kỳ thứ tự nào nó muốn.

"Thủ thuật" trong truy vấn trong câu trả lời của tôi (ở trên) phụ thuộc vào hành vi có thể dành riêng cho một số phiên bản của MySQL.

Trường hợp thử nghiệm:

điền bảng

CREATE TABLE foo2 (id INT PRIMARY KEY, role VARCHAR(20)) ENGINE=InnoDB;
CREATE TABLE foo3 (id INT PRIMARY KEY, role VARCHAR(20)) ENGINE=InnoDB;

INSERT INTO foo2 (id, role) VALUES 
  (1,'sam'),(2,'frodo'),(3,'aragorn'),(4,'pippin'),(5,'gandalf');
INSERT INTO foo3 (id, role) VALUES 
  (1,'gimli'),(2,'boromir'),(3,'elron'),(4,'merry'),(5,'legolas');

truy vấn

SELECT a.*
  FROM ( SELECT s.id, s.role
           FROM foo2 s
          ORDER BY s.role
       ) a
 UNION ALL
SELECT b.*
  FROM ( SELECT t.id, t.role
           FROM foo3 t
          ORDER BY t.role
       ) b

tập kết quả được trả về

    id  role     
 ------  ---------
      3  aragorn  
      2  frodo    
      5  gandalf  
      4  pippin   
      1  sam      
      2  boromir  
      3  elron    
      1  gimli    
      5  legolas  
      4  merry    

Các hàng từ foo2 được trả về "theo thứ tự", theo sau là các hàng từ foo3 , một lần nữa, "theo thứ tự".

Lưu ý (một lần nữa) rằng hành vi này là KHÔNG đảm bảo. (Hành vi mà chúng tôi quan sát được là một tác dụng phụ của cách MySQL xử lý các chế độ xem nội tuyến (bảng dẫn xuất). Hành vi này có thể khác trong các phiên bản sau 5.5.)

Nếu bạn cần các hàng được trả về theo một thứ tự cụ thể, thì hãy chỉ định một ORDER BY mệnh đề cho truy vấn ngoài cùng. Và thứ tự đó sẽ áp dụng cho toàn bộ tập kết quả.

Như tôi đã đề cập trước đó, nếu tôi cần các hàng từ truy vấn đầu tiên trước, sau đó là truy vấn thứ hai, tôi sẽ bao gồm cột "dấu phân biệt" trong mỗi truy vấn và sau đó bao gồm cột "dấu phân biệt" trong mệnh đề ORDER BY. Tôi cũng sẽ loại bỏ các chế độ xem nội tuyến và làm điều gì đó như sau:

SELECT s.id, s.role, 's' AS src
  FROM foo2 s
 UNION ALL
SELECT t.id, t.role, 't' AS src
  FROM foo3 t
 ORDER BY src, role


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Các tiêu chuẩn / quy ước về tên cột MySQL

  2. Chọn các hàng trong đó trường trống bằng cách sử dụng các câu lệnh được chuẩn bị sẵn trong PHP PDO và MySQL

  3. đếm không có nhóm

  4. tạo bảng mysql nếu nó không tồn tại

  5. HANDLER FOR NOT FOUND hoạt động như thế nào và cách sử dụng nó là gì?