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

PostgreSQL unnest () với số phần tử

Postgres 9.4 trở lên

Sử dụng WITH ORDINALITY cho các hàm trả về thiết lập:

Khi một hàm trong FROM mệnh đề có hậu tố là WITH ORDINALITY , một bigint cột được nối vào đầu ra bắt đầu từ 1 và tăng thêm 1 cho mỗi hàng của đầu ra của hàm. Điều này hữu ích nhất trong trường hợp đặt các hàm trả về chẳng hạn như unnest() .

Kết hợp với LATERAL tính năng trong pg 9.3+ và theo chủ đề này trên pgsql-hacker, truy vấn trên hiện có thể được viết là:

SELECT t.id, a.elem, a.nr
FROM   tbl AS t
LEFT   JOIN LATERAL unnest(string_to_array(t.elements, ','))
                    WITH ORDINALITY AS a(elem, nr) ON TRUE;

LEFT JOIN ... ON TRUE giữ nguyên tất cả các hàng trong bảng bên trái, ngay cả khi biểu thức bảng bên phải trả về không có hàng nào. Nếu điều đó không có gì đáng lo ngại, bạn có thể sử dụng cách khác tương đương, bớt chi tiết hơn biểu mẫu có CROSS JOIN LATERAL ngầm định :

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr);

Hoặc đơn giản hơn nếu dựa trên mảng thực tế (arr là một cột mảng):

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr);

Hoặc thậm chí, với cú pháp tối thiểu:

SELECT id, a, ordinality
FROM   tbl, unnest(arr) WITH ORDINALITY a;

a tự động là bảng bí danh cột. Tên mặc định của cột thứ tự đã thêm là ordinality . Nhưng tốt hơn (an toàn hơn, rõ ràng hơn) nếu thêm bí danh cột rõ ràng và cột đủ điều kiện trong bảng.

Postgres 8,4 - 9,3

Với row_number() OVER (PARTITION BY id ORDER BY elem) bạn nhận được các số theo thứ tự sắp xếp, không phải số thứ tự của vị trí thứ tự ban đầu trong chuỗi.

Bạn chỉ cần bỏ qua ORDER BY :

SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM  (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t;

Trong khi điều này bình thường hoạt động và tôi chưa bao giờ thấy nó không thành công trong các truy vấn đơn giản, PostgreSQL khẳng định không có gì liên quan đến thứ tự của các hàng mà không có ORDER BY . Nó hoạt động do một chi tiết triển khai.

Để đảm bảo số thứ tự trong số các phần tử trong chuỗi được phân tách bằng khoảng trống :

SELECT id, arr[nr] AS elem, nr
FROM  (
   SELECT *, generate_subscripts(arr, 1) AS nr
   FROM  (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
   ) sub;

Hoặc đơn giản hơn nếu dựa trên mảng thực tế :

SELECT id, arr[nr] AS elem, nr
FROM  (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t;

Câu trả lời liên quan trên dba.SE:

  • Làm cách nào để bảo toàn thứ tự ban đầu của các phần tử trong một mảng chưa được sắp xếp?

Postgres 8.1 - 8.4

Chưa có tính năng nào trong số những tính năng này:RETURNS TABLE , generate_subscripts() , unnest() , array_length() . Nhưng điều này hoạt động:

CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1
 FROM   generate_series(array_lower($1,1), array_upper($1,1)) i';

Đặc biệt lưu ý rằng chỉ số mảng có thể khác với vị trí thứ tự của các phần tử. Hãy xem xét bản trình diễn này với một chức năng mở rộng :

CREATE FUNCTION f_unnest_ord_idx(anyarray, OUT val anyelement, OUT ordinality int, OUT idx int)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1, i
 FROM   generate_series(array_lower($1,1), array_upper($1,1)) i';

SELECT id, arr, (rec).*
FROM  (
   SELECT *, f_unnest_ord_idx(arr) AS rec
   FROM  (VALUES (1, '{a,b,c}'::text[])  --  short for: '[1:3]={a,b,c}'
               , (2, '[5:7]={a,b,c}')
               , (3, '[-9:-7]={a,b,c}')
      ) t(id, arr)
   ) sub;

 id |       arr       | val | ordinality | idx
----+-----------------+-----+------------+-----
  1 | {a,b,c}         | a   |          1 |   1
  1 | {a,b,c}         | b   |          2 |   2
  1 | {a,b,c}         | c   |          3 |   3
  2 | [5:7]={a,b,c}   | a   |          1 |   5
  2 | [5:7]={a,b,c}   | b   |          2 |   6
  2 | [5:7]={a,b,c}   | c   |          3 |   7
  3 | [-9:-7]={a,b,c} | a   |          1 |  -9
  3 | [-9:-7]={a,b,c} | b   |          2 |  -8
  3 | [-9:-7]={a,b,c} | c   |          3 |  -7

So sánh:

  • Chuẩn hóa các chỉ số con của mảng cho mảng 1 chiều để chúng bắt đầu bằng 1


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nâng cấp lên PostgreSQL13

  2. Psycopg2 Chèn vào bảng với trình giữ chỗ

  3. Làm cách nào để ghi các truy vấn PostgreSQL?

  4. Thêm đối tượng dict vào postgresql

  5. PostgreSQL 12:Triển khai K-Nearest Neighbor Space Partitioned Generated Tree Indexes