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

Có cách tiếp cận tiêu chuẩn nào để xử lý các mảng (tập hợp) không có thứ tự trong PostgreSQL không?

Không có cách tích hợp nào vào lúc này.

Dưới dạng mảng

Nếu bạn thường xuyên chuẩn hóa chúng khi lưu, bạn có thể coi mảng là tập hợp, bằng cách luôn lưu trữ chúng được sắp xếp và loại bỏ trùng lặp. Sẽ thật tuyệt nếu PostgreSQL có một hàm C tích hợp để làm điều này, nhưng nó không. Tôi đã xem qua cách viết một cái nhưng API mảng C thật kinh khủng , vì vậy, mặc dù tôi đã viết một loạt các tiện ích mở rộng, tôi vẫn cẩn thận tránh xa cái này.

Nếu bạn không bận tâm về hiệu suất kém vừa phải, bạn có thể làm điều đó trong SQL:

CREATE OR REPLACE FUNCTION array_uniq_sort(anyarray) RETURNS anyarray AS $$
SELECT array_agg(DISTINCT f ORDER BY f) FROM unnest($1) f;
$$ LANGUAGE sql IMMUTABLE;

sau đó gói tất cả các lưu trong lệnh gọi đến array_uniq_sort hoặc thực thi nó bằng một trình kích hoạt. Sau đó, bạn có thể chỉ cần so sánh các mảng của mình cho bằng nhau. Bạn có thể tránh array_uniq_sort yêu cầu dữ liệu từ ứng dụng nếu thay vào đó bạn chỉ thực hiện sắp xếp / duy nhất ở phía ứng dụng.

Nếu bạn làm điều này xin vui lòng lưu trữ "bộ" của bạn dưới dạng cột mảng, như text[] , không phải văn bản được phân tách bằng dấu phẩy hoặc dấu cách. Xem câu hỏi này vì một số lý do.

Bạn cần chú ý một số điều, chẳng hạn như thực tế là phôi giữa các mảng chặt chẽ hơn phôi giữa các loại cơ sở của chúng. Ví dụ:

regress=> SELECT 'a' = 'a'::varchar, 'b' = 'b'::varchar;
 ?column? | ?column? 
----------+----------
 t        | t
(1 row)

regress=> SELECT ARRAY['a','b'] = ARRAY['a','b']::varchar[];
ERROR:  operator does not exist: text[] = character varying[]
LINE 1: SELECT ARRAY['a','b'] = ARRAY['a','b']::varchar[];
                              ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
regress=> SELECT ARRAY['a','b']::varchar[] = ARRAY['a','b']::varchar[];
 ?column? 
----------
 t
(1 row)

Các cột như vậy có thể lập chỉ mục GiST cho các hoạt động như mảng chứa hoặc chồng chéo mảng; xem tài liệu PostgreSQL về lập chỉ mục mảng.

Dưới dạng hàng chuẩn hóa

Tùy chọn khác là chỉ lưu trữ các hàng chuẩn hóa bằng một khóa phù hợp. Tôi vẫn sử dụng array_agg để sắp xếp và so sánh chúng, vì các hoạt động tập hợp SQL có thể khó sử dụng cho việc này (đặc biệt là do thiếu hoạt động XOR / sự khác biệt tập hợp hai mặt).

Điều này thường được gọi là EAV (thực thể-thuộc tính-giá trị). Bản thân tôi không phải là một người hâm mộ, nhưng đôi khi nó cũng có vị trí của nó. Ngoại trừ việc bạn đang sử dụng nó mà không có giá trị value thành phần.

Bạn tạo một bảng:

CREATE TABLE item_attributes (
    item_id integer references items(id),
    attribute_name text,
    primary key(item_id, attribute_name)
);

và chèn một hàng cho mỗi mục nhập đã đặt cho mỗi mục, thay vì mỗi mục có một cột có giá trị mảng. Ràng buộc duy nhất được thực thi bởi khóa chính đảm bảo rằng không mục nào có thể có bản sao của một thuộc tính nhất định. Thứ tự thuộc tính không liên quan / không xác định.

So sánh có thể được thực hiện với các toán tử bộ SQL như EXCEPT hoặc sử dụng array_agg(attribute_name ORDER BY attribute_name) để tạo thành các mảng được sắp xếp nhất quán để so sánh.

Việc lập chỉ mục được giới hạn trong việc xác định xem một mặt hàng nhất định có / không có một thuộc tính nhất định hay không.

Cá nhân tôi muốn sử dụng mảng theo cách tiếp cận này.

hstore

Bạn cũng có thể sử dụng hstores với các giá trị trống để lưu trữ các tập hợp, làm khóa hstore loại bỏ trùng lặp. 9.4 của jsonb cũng sẽ hoạt động cho việc này.

regress=# create extension hstore;
CREATE EXTENSION
regress=# SELECT hstore('a => 1, b => 1') = hstore('b => 1, a => 1, b => 1');
 ?column? 
----------
 t
(1 row)

Tuy nhiên, nó chỉ thực sự hữu ích cho các loại văn bản. ví dụ:

regress=# SELECT hstore('"1.0" => 1, "2.0" => 1') = hstore('"1.00" => 1, "1.000" => 1, "2.0" => 1');
 ?column? 
----------
 f
(1 row)

và tôi nghĩ nó xấu xí. Vì vậy, một lần nữa, tôi thích mảng.

Chỉ dành cho mảng số nguyên

intarray tiện ích mở rộng cung cấp các chức năng hữu ích, nhanh chóng để xử lý mảng như một tập hợp. Chúng chỉ khả dụng cho mảng số nguyên nhưng chúng thực sự hữu ích.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Autoincrement trong liquibase

  2. Từ Now () đến Current_timestamp trong Postgresql

  3. Khóa và giao dịch trong các bưu điện sẽ chặn một truy vấn

  4. Cách chuyển đổi boolean trong postgres trong một truy vấn

  5. Các giới hạn trên lược đồ PostgreSQL thay đổi bên trong các giao dịch?