Làm thế nào để ORDER BY FIELD () trong MySQL hoạt động bên trong


37

Tôi hiểu cách ORDER BYhoạt động của mệnh đề và cách thức FIELD()hoạt động của chức năng. Điều tôi muốn hiểu là làm thế nào cả hai cùng làm việc để sắp xếp. Các hàng được lấy như thế nào và thứ tự sắp xếp bắt nguồn như thế nào

+----+---------+
| id |  name   |
+----+---------+
|  1 | stan    |
|  2 | kyle    |
|  3 | kenny   |
|  4 | cartman |
+----+---------+ 

SELECT * FROM mytable WHERE id IN (3,2,1,4) ORDER BY FIELD(id,3,2,1,4)

Các truy vấn ở trên sẽ dẫn đến

+----+---------+
| id |  name   |
+----+---------+
|  3 | kenny   |
|  2 | kyle    |
|  1 | stan    |
|  4 | cartman |
+----+---------+ 

một cái gì đó tương tự như nói ĐẶT HÀNG 3, 2, 1, 4

CÂU HỎI

  • Làm thế nào để làm việc này trong nội bộ?
  • Làm thế nào để MySQL có được các hàng và tính toán thứ tự sắp xếp?
  • Làm thế nào để MySQL biết nó phải sắp xếp theo cột id?

1
thử biến thể truy vấn này: SELECT *, FIELD(id,3,2,1,4) AS f FROM mytable WHERE id IN (3,2,1,4);Sau đó thêm ORDER BY fhoặc ORDER BY FIELD(id,3,2,1,4)thử lại.
ypercubeᵀᴹ

Câu trả lời:


64

Đối với hồ sơ

SELECT * FROM mytable WHERE id IN (1,2,3,4) ORDER BY FIELD(id,3,2,1,4);

cũng nên hoạt động vì bạn không phải sắp xếp danh sách trong WHEREmệnh đề

Về cách thức hoạt động,

  • FIELD () là một hàm trả về vị trí chỉ mục của danh sách được phân cách bằng dấu phẩy nếu giá trị bạn đang tìm kiếm tồn tại.

    • NẾU id = 1, sau đó FIELD (id, 3,2,1,4) trả về 3 (vị trí có 1 trong danh sách)
    • NẾU id = 2, sau đó FIELD (id, 3,2,1,4) trả về 2 (vị trí có 2 trong danh sách)
    • NẾU id = 3, sau đó FIELD (id, 3,2,1,4) trả về 1 (vị trí có 3 trong danh sách)
    • NẾU id = 4, sau đó FIELD (id, 3,2,1,4) trả về 4 (vị trí có 4 trong danh sách)
    • NẾU id = bất cứ điều gì khác, sau đó FIELD (id, 3,2,1,4) trả về 0 (không có trong danh sách)
  • Các ORDER BYgiá trị được đánh giá bởi những gì FIELD () trả về

Bạn có thể tạo tất cả các loại đơn đặt hàng ưa thích

Ví dụ, bằng cách sử dụng ) (NẾU chức năng

SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0),FIELD(id,3,2,1,4);

Điều này sẽ khiến 4 id đầu tiên xuất hiện ở đầu danh sách, nếu không, nó sẽ xuất hiện ở cuối. Tại sao?

Trong ORDER BY, bạn có được 0 hoặc 1.

  • Nếu cột đầu tiên là 0, làm cho bất kỳ 4 id đầu tiên xuất hiện
  • Nếu cột đầu tiên là 1, làm cho nó xuất hiện sau đó

Hãy lật nó với DESC trong cột đầu tiên

SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0) DESC,FIELD(id,3,2,1,4);

Trong ORDER BY, bạn vẫn nhận được 0 hoặc 1.

  • Nếu cột đầu tiên là 1, hãy tạo mọi thứ trừ 4 id đầu tiên xuất hiện.
  • Nếu cột đầu tiên là 0, hãy tạo 4 id đầu tiên xuất hiện theo thứ tự ban đầu

CÂU HỎI THỰC TẾ CỦA BẠN

Nếu bạn thực sự muốn có nội bộ về điều này, hãy xem trang 189 và 192 của Sách

Nội bộ MySQL

cho một lần lặn sâu thực sự.

Về bản chất, có một lớp C ++ được gọi là ORDER *order(Cây ORDER BYbiểu thức). Trong JOIN::prepare, *orderđược sử dụng trong một chức năng gọi là setup_order(). Tại sao ở giữa JOINlớp? Mọi truy vấn, thậm chí một truy vấn đối với một bảng duy nhất luôn được xử lý dưới dạng THAM GIA (Xem bài đăng của tôi Có sự khác biệt thực thi giữa điều kiện THAM GIA và điều kiện WHERE không? )

Mã nguồn cho tất cả điều này là sql/sql_select.cc

Rõ ràng, ORDER BYcây sẽ tổ chức đánh giá FIELD(id,3,2,1,4). Do đó, các số 0,1,2,3,4 là các giá trị được sắp xếp trong khi mang tham chiếu đến hàng liên quan.


1
Đây là một lời giải thích xuất sắc xuất sắc. Sử dụng các phương thức này tôi đã có thể nhận được 3 đơn hàng, giá trị đầu tiên chính là tối đa của tập hợp, sau đó là FIELD, sau đó bằng một cột khác cho các đơn hàng không nằm trong tập FIELD. Một cái gì đó tôi đã không mơ về một thời gian trước đây. Cảm ơn đã dành thời gian để thực sự giải thích làm thế nào điều này thực sự hoạt động.
Lizardx

Giả sử rằng có Ncác giá trị trong cả hai INFIELD. Trong ví dụ này N=4. Tôi có hiểu chính xác rằng truy vấn này sẽ thực hiện ít nhất các ~N^2hoạt động. Bởi vì mỗi FIELDtính toán tạo ra ~Nsự so sánh một lần cho mỗi hàng. Nếu vậy thì điều này khá chậm đối với lớn NCó lẽ đó không phải là một cách tiếp cận tốt?
Gherman

@Gherman FIELD()Hàm nên là một O(1)phép toán vì FIELD()có chỉ số bằng số id. Vì vậy, tôi không thấy gì khác ngoài việc O(n)dựa trên các hàng. Tôi không thấy FIELD()thực hiện bất kỳ hoạt động lặp đi lặp lại như GREATEST()sẽ cần phải làm.
RolandoMySQLDBA

@RolandoMySQLDBA Quan điểm của tôi là nếu FIELDNđối số để so sánh thì nó sẽ thực hiện Nso sánh. Làm thế nào khác nó sẽ so sánh một số với Ncác số khác nếu không bằng cách làm O(N)? Khả năng duy nhất tôi có thể nghĩ đến là một loại tối ưu hóa thông qua cấu trúc dữ liệu đặc biệt như hàm băm hoặc cây đối số. Trên thực tế tôi biết rằng INcó tối ưu hóa như vậy. Tôi không biết về FIELD. Bạn có ý nghĩa gì bởi một "chỉ số số"?
Gherman

1
Xin chào @RaymondNijland, Câu lệnh CASE dễ hiểu hơn. Đối với trường hợp này, đường cú pháp chỉ có ít chữ viết hơn.
RolandoMySQLDBA

1

Có thể điều này sẽ quá xa so với mã thực tế nên mức độ không đủ thấp so với những gì bạn muốn:

Khi MySQL không thể sử dụng chỉ mục để truy xuất dữ liệu theo thứ tự được sắp xếp, nó sẽ tạo một bảng / kết quả tạm thời với tất cả các cột được chọn và một số dữ liệu bổ sung - một trong số đó là một cột để lưu trữ kết quả của giá trị biểu thức ORDER BY cho mỗi hàng - sau đó nó sẽ gửi bảng tmp này đến một rutine "filesort" với thông tin cột nào sẽ được sắp xếp theo. Sau đó, các hàng được sắp xếp theo thứ tự để nó có thể chọn từng cái một và trả về các cột được chọn.


Giải thích này không tính đến FIELDchức năng tính toán như thế nào . Tôi sợ nó có thể có một tác động đáng kể đến hiệu suất.
Gherman

@Gherman Tôi không nghĩ vậy, trừ khi bạn đang sử dụng danh sách các đối số rất dài (vì hàm này là tuyến tính với số lượng đối số . Truy cập dữ liệu chậm hơn so với so sánh đơn giản.
jkavalik

Vâng, danh sách dài các đối số. Có nhiều đối số như có các bản ghi trong ví dụ này.
Gherman

Tôi sẽ chỉ gắn nhãn hàng trăm hoặc hàng nghìn, và sau đó bạn sẽ gặp các vấn đề khác (kích thước truy vấn, v.v.)
jkavalik

Tại sao không phải hàng trăm kết quả? Có nhiều không
Gherman
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.