Một ví dụ rất đơn giản sẽ là:
> SELECT * FROM tab ORDER BY col USING <
Nhưng đây là nhàm chán, bởi vì đây là không có gì bạn không thể có được với truyền thống ORDER BY col ASC
.
Danh mục tiêu chuẩn cũng không đề cập đến bất kỳ điều gì thú vị về các toán tử/toán tử so sánh lạ. Bạn có thể nhận được một danh sách trong số họ:
> SELECT amoplefttype::regtype, amoprighttype::regtype, amopopr::regoper
FROM pg_am JOIN pg_amop ON pg_am.oid = pg_amop.amopmethod
WHERE amname = 'btree' AND amopstrategy IN (1,5);
Bạn sẽ nhận thấy rằng có phần lớn là <
và >
chức năng với nhiều loại nguyên thủy như integer
, date
vv và một số chi tiết cho các mảng và vectơ và vân vân. Không một nhà khai thác nào trong số này sẽ giúp bạn có được một đơn đặt hàng tùy chỉnh.
Trong hầu hết trường hợp yêu cầu đặt hàng tùy chỉnh, bạn có thể lấy đi bằng cách sử dụng một cái gì đó như ... ORDER BY somefunc(tablecolumn) ...
nơi ánh xạ giá trị một cách thích hợp. Bởi vì điều đó làm việc với mọi cơ sở dữ liệu, đây cũng là cách phổ biến nhất. Đối với những điều đơn giản, bạn thậm chí có thể viết một biểu thức thay vì một chức năng tùy chỉnh.
bánh răng Switching lên
ORDER BY ... USING
có ý nghĩa trong một số trường hợp:
- Trật tự là rất phổ biến, đó là lừa
somefunc
không hoạt động.
- Bạn làm việc với loại không nguyên thủy (như
point
, circle
hoặc số ảo) và bạn không muốn lặp lại chính mình trong các truy vấn của mình với các phép tính lạ.
- Tập dữ liệu bạn muốn sắp xếp quá lớn, hỗ trợ bởi chỉ mục là mong muốn hoặc thậm chí được yêu cầu.
Tôi sẽ tập trung vào các kiểu dữ liệu phức tạp: thường có nhiều cách để sắp xếp chúng theo cách hợp lý.Ví dụ tốt là point
: Bạn có thể "đặt hàng" chúng theo khoảng cách tới (0,0) hoặc trước tiên là x, sau đó là y hoặc chỉ bằng y hoặc bất kỳ thứ gì bạn muốn.
Tất nhiên, PostgreSQL có khai thác được xác định trước cho point
:
> CREATE TABLE p (p point);
> SELECT p <-> point(0,0) FROM p;
Nhưng none trong số họ bị tuyên bố có thể sử dụng cho ORDER BY
theo mặc định (xem ở trên):
> SELECT * FROM p ORDER BY p;
ERROR: could not identify an ordering operator for type point
TIP: Use an explicit ordering operator or modify the query.
khai thác đơn giản cho point
là các toán tử "bên dưới" và "ở trên" <^
và >^
. Họ so sánh chỉ đơn giản là phần y
của điểm. Nhưng:
> SELECT * FROM p ORDER BY p USING >^;
ERROR: operator > is not a valid ordering operator
TIP: Ordering operators must be "<" or ">" members of __btree__ operator families.
ORDER BY USING
đòi hỏi một nhà điều hành với ngữ nghĩa được định nghĩa: Rõ ràng nó phải là một nhà điều hành nhị phân, nó phải chấp nhận cùng loại như các đối số và nó phải trả lại boolean. Tôi nghĩ rằng nó cũng phải là transitive (nếu là < b và b < c thì một số < c). Có thể có nhiều yêu cầu hơn. Nhưng tất cả các yêu cầu này cũng cần thiết cho việc đặt hàng btree -index phù hợp. Điều này giải thích các thông báo lỗi lạ có chứa tham chiếu đến btree.
ORDER BY USING
cũng đòi hỏi không chỉ một nhà điều hành phải được xác định nhưng một lớp hành và một gia đình hành. Trong khi một có thể thực hiện sắp xếp chỉ với một toán tử, PostgreSQL cố sắp xếp một cách hiệu quả và giảm thiểu các so sánh. Do đó, một số toán tử được sử dụng ngay cả khi bạn chỉ định một - các toán tử khác phải tuân thủ một số ràng buộc toán học nhất định - tôi đã đề cập đến sự chuyển đổi, nhưng có nhiều hơn.
Gears Switching lên
Hãy xác định một cái gì đó phù hợp: Một nhà điều hành cho điểm mà so sánh chỉ là phần y
.
Bước đầu tiên là tạo gia đình nhà điều hành tùy chỉnh có thể được sử dụng theo phương pháp truy cập chỉ mục btree chỉ mục. see
> CREATE OPERATOR FAMILY xyzfam USING btree; -- superuser access required!
CREATE OPERATOR FAMILY
Tiếp theo, chúng tôi phải cung cấp hàm so sánh trả về -1, 0, +1 khi so sánh hai điểm. Chức năng này S 01N được gọi nội bộ!
> CREATE FUNCTION xyz_v_cmp(p1 point, p2 point) RETURNS int
AS $$BEGIN RETURN btfloat8cmp(p1[1],p2[1]); END $$ LANGUAGE plpgsql;
CREATE FUNCTION
Tiếp theo, chúng tôi xác định lớp toán tử cho gia đình. See the manual để giải thích về các con số.
> CREATE OPERATOR CLASS xyz_ops FOR TYPE point USING btree FAMILY xyzfam AS
OPERATOR 1 <^ ,
OPERATOR 3 ?- ,
OPERATOR 5 >^ ,
FUNCTION 1 xyz_v_cmp(point, point) ;
CREATE OPERATOR CLASS
Bước này kết hợp một số toán tử và chức năng và cũng xác định mối quan hệ và ý nghĩa của chúng. Ví dụ: OPERATOR 1
có nghĩa là: Đây là toán tử cho các thử nghiệm less-than
.
Bây giờ các nhà khai thác <^
và '> ^' có thể được sử dụng trong ORDER BY USING
:
> INSERT INTO p SELECT point(floor(random()*100), floor(random()*100)) FROM generate_series(1, 5);
INSERT 0 5
> SELECT * FROM p ORDER BY p USING >^;
p
---------
(17,8)
(74,57)
(59,65)
(0,87)
(58,91)
Voila - sắp xếp theo y.
Để tổng hợp:ORDER BY ... USING
là một giao diện thú vị dưới mui xe của PostgreSQL. Nhưng không có gì bạn sẽ yêu cầu bất cứ lúc nào sớm trừ khi bạn làm việc trong rất các lĩnh vực cụ thể của công nghệ cơ sở dữ liệu.
Ví dụ khác có thể được tìm thấy in the Postgres docs. với mã nguồn cho ví dụ here và here. Ví dụ này cũng cho thấy cách tạo các toán tử.
Ý anh là gì bởi "trật tự xen kẽ"? –