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

Mệnh đề ORDER BY ... USING trong PostgreSQL

Một ví dụ rất đơn giản sẽ là:

> SELECT * FROM tab ORDER BY col USING <

Nhưng điều này thật nhàm chán, bởi vì đây là điều bạn không thể có được với ORDER BY col ASC truyền thống .

Ngoài ra, danh mục tiêu chuẩn không đề cập đến bất kỳ điều gì thú vị về các hàm / toán tử so sánh kỳ lạ. Bạn có thể lấy danh sách chúng:

    > 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 hầu hết có <> các hàm cho các kiểu nguyên thủy như integer , date vv và một số khác cho mảng và vectơ, v.v. Không nhà khai thác nào trong số này sẽ giúp bạn đặt hàng tùy chỉnh.

Trong hầu hết trong trường hợp yêu cầu đặt hàng tùy chỉnh, bạn có thể sử dụng một cái gì đó như ... ORDER BY somefunc(tablecolumn) ... ở đâu somefunc ánh xạ các giá trị một cách thích hợp. Vì cách đó hoạt động với mọi cơ sở dữ liệu nên đây cũng là cách phổ biến nhất. Đối với những thứ đơn giản, bạn thậm chí có thể viết một biểu thức thay vì một hàm tùy chỉnh.

Đang chuyển đổi bánh răng

ORDER BY ... USING có ý nghĩa trong một số trường hợp:

  • Thứ tự không phổ biến đến mức somefunc mánh khóe không hiệu quả.
  • Bạn làm việc với kiểu không nguyên thủy (như point , circle hoặc các con số tưởng tượng) và bạn không muốn lặp lại các phép tính kỳ lạ trong các truy vấn của mình.
  • Tập dữ liệu bạn muốn sắp xếp quá lớn nên cần có hoặc thậm chí cần phải có sự hỗ trợ của chỉ mục.

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 một cách hợp lý. Một ví dụ điển hình là point :Bạn có thể "đặt hàng" chúng theo khoảng cách đến (0,0) hoặc theo x đầu tiên, sau đó đến y hoặc chỉ bởi y hoặc bất kỳ thứ gì khác mà bạn muốn.

Tất nhiên, PostgreSQL toán tử được xác định trước cho point :

    > CREATE TABLE p ( p point );
    > SELECT p <-> point(0,0) FROM p;

Nhưng không trong số chúng được tuyên bố là có thể sử dụng được 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.

Các toán tử đơn giản cho point là các toán tử "bên dưới" và "bên trên" <^>^ . Họ so sánh đơn giản là y một phần 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 yêu cầu một toán tử với ngữ nghĩa xác định:Rõ ràng nó phải là một toán tử nhị phân, nó phải chấp nhận cùng kiểu với các đối số và nó phải trả về boolean. Tôi nghĩ nó cũng phải có tính bắc cầu (nếu a btree phù hợp -đặt hàng lập chỉ mục. Đ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 không chỉ yêu cầu một toán tử được định nghĩa nhưng là một lớp toán tử và một họ nhà điều 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ố gắng sắp xếp hiệu quả và giảm thiểu 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ủ các ràng buộc toán học nhất định - Tôi đã đề cập đến tính chuyển tiếp, nhưng còn nhiều toán tử hơn.

Đang chuyển bánh răng lên

Hãy xác định một cái gì đó phù hợp:Một toán tử cho các điểm chỉ so sánh y một phần.

Bước đầu tiên là tạo một nhóm toán tử tùy chỉnh có thể được sử dụng bởi btree phương pháp truy cập chỉ mục. xem

    > CREATE OPERATOR FAMILY xyzfam USING btree;   -- superuser access required!
    CREATE OPERATOR FAMILY

Tiếp theo, chúng ta phải cung cấp một hàm so sánh trả về -1, 0, +1 khi so sánh hai điểm. Chức năng này WILL đượ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 ta định nghĩa lớp toán tử cho họ. Xem sách hướng dẫn để biết 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à hàm, đồng thời xác định mối quan hệ và ý nghĩa của chúng. Ví dụ:OPERATOR 1 nghĩa là:Đây là toán tử cho less-than kiểm tra.

Bây giờ các toán tử <^>^ 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)

Thì đấy - được sắp xếp theo y .

Tóm lại: ORDER BY ... USING là một giao diện thú vị dưới lớp vỏ của PostgreSQL. Nhưng bạn sẽ sớm không yêu cầu gì 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.

Một ví dụ khác có thể được tìm thấy trong tài liệu Postgres. với mã nguồn cho ví dụ ở đây và ở đây. Ví dụ này cũng cho thấy cách tạo toán tử.



  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ách nhanh chóng loại bỏ một người dùng có các đặc quyền hiện có

  2. Thúc đẩy hiệu suất cho PostgreSQL với HAProxy

  3. Cách liệt kê các khóa ngoại của bảng

  4. Làm cách nào để di chuyển cơ sở dữ liệu PostgreSQL sang SQLServer?

  5. Cách nhanh nhất để thực hiện chèn hàng loạt vào Postgres là gì?