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

THAM GIA LEFT OUTER trên cột mảng có nhiều giá trị

Có, toán tử chồng chéo && có thể sử dụng chỉ mục GIN trên mảng . Rất hữu ích cho các truy vấn này để tìm các hàng có một người nhất định (1 ) giữa một loạt các tác nhân:

SELECT * FROM eg_assoc WHERE actors && '{1}'::int[]

Tuy nhiên , logic truy vấn của bạn là ngược lại, tìm kiếm tất cả những người được liệt kê trong các mảng trong eg_assoc . Chỉ số GIN là không giúp đỡ ở đây. Chúng tôi chỉ cần chỉ mục btree của PK person.id .

Truy vấn thích hợp

Khái niệm cơ bản:

Các truy vấn sau bảo tồn các mảng ban đầu chính xác như đã cho , bao gồm các phần tử có thể trùng lặp và thứ tự ban đầu của các phần tử. Hoạt động cho mảng 1 chiều . Các kích thước bổ sung được gấp lại thành một chiều duy nhất. Việc bảo toàn nhiều thứ nguyên phức tạp hơn (nhưng hoàn toàn có thể):

WITH ORDINALITY trong Postgres 9.4 trở lên

SELECT aid, actors
     , ARRAY(SELECT name
             FROM   unnest(e.actors) WITH ORDINALITY a(id, i)
             JOIN   eg_person p USING (id)
             ORDER  BY a.i) AS act_names
     , benefactors
     , ARRAY(SELECT name
             FROM   unnest(e.benefactors) WITH ORDINALITY b(id, i)
             JOIN   eg_person USING (id)
             ORDER  BY b.i) AS ben_names
FROM   eg_assoc e;

LATERAL truy vấn

Đối với PostgreSQL 9.3+ .

SELECT e.aid, e.actors, a.act_names, e.benefactors, b.ben_names
FROM   eg_assoc e
, LATERAL (
   SELECT ARRAY( SELECT name
                 FROM   generate_subscripts(e.actors, 1) i
                 JOIN   eg_person p ON p.id = e.actors[i]
                 ORDER  BY i)
   ) a(act_names)
, LATERAL (
   SELECT ARRAY( SELECT name
                 FROM   generate_subscripts(e.benefactors, 1) i
                 JOIN   eg_person p ON p.id = e.benefactors[i]
                 ORDER  BY i)
   ) b(ben_names);

db <> fiddle tại đây với một số biến thể.
sqlfiddle

Chi tiết tinh tế:Nếu một người không được tìm thấy, nó chỉ bị rơi. Cả hai truy vấn này đều tạo ra một mảng trống ( '{}' ) nếu không tìm thấy người nào cho toàn bộ mảng. Các kiểu truy vấn khác sẽ trả về NULL . Tôi đã thêm các biến thể vào fiddle.

Truy vấn phụ có liên quan

Đối với Postgres 8.4+ (trong đó generate_subsrcipts() đã được giới thiệu):

SELECT aid, actors
     , ARRAY(SELECT name
             FROM   generate_subscripts(e.actors, 1) i
             JOIN   eg_person p ON p.id = e.actors[i]
             ORDER  BY i) AS act_names
     , benefactors
     , ARRAY(SELECT name
             FROM   generate_subscripts(e.benefactors, 1) i
             JOIN   eg_person p ON p.id = e.benefactors[i]
             ORDER  BY i) AS ben_names
FROM   eg_assoc e;

Vẫn có thể hoạt động tốt nhất, ngay cả trong Postgres 9.3.
ARRAY phương thức khởi tạo nhanh hơn array_agg() . Xem:

Truy vấn không thành công của bạn

truy vấn được cung cấp bởi @a_horse dường như để thực hiện công việc, nhưng nó không đáng tin cậy, gây hiểu lầm, có khả năng không chính xác và không cần thiết phải trả giá đắt.

  1. Tham gia chéo proxy vì hai liên kết không liên quan. Một mẫu chống lén lút. Xem:

    Đã sửa bề ngoài với DISTINCT trong array_agg() để loại bỏ các bản sao được tạo ra, nhưng đó thực sự là việc tô son cho một con lợn. Nó cũng loại bỏ các bản sao trong bản gốc bởi vì không thể phân biệt được sự khác biệt vào thời điểm này - điều này có thể không chính xác.

  2. Biểu thức a_person.id = any(eg_assoc.actors) hoạt động , nhưng loại bỏ các bản sao từ kết quả (xảy ra hai lần trong truy vấn này), sai trừ khi được chỉ định.

  3. Thứ tự ban đầu của các phần tử mảng không được giữ nguyên . Điều này là khó khăn nói chung. Nhưng nó trở nên trầm trọng hơn trong truy vấn này, bởi vì các tác nhân và nhà hảo tâm được nhân lên và phân biệt một lần nữa, điều này đảm bảo đặt hàng tùy ý.

  4. Không có bí danh cột nào trong SELECT bên ngoài dẫn đến các tên cột trùng lặp, điều này khiến một số ứng dụng khách bị lỗi (không hoạt động trong fiddle mà không có bí danh).

  5. min(actors)min(benefactors) Vô dụng. Thông thường người ta sẽ chỉ thêm các cột vào GROUP BY thay vì giả-tập hợp chúng. Nhưng eg_assoc.aid vẫn là cột PK (bao gồm toàn bộ bảng trong GROUP BY ), vì vậy điều đó thậm chí không cần thiết. Chỉ là actors, benefactors .

Tổng hợp toàn bộ kết quả là lãng phí thời gian và công sức để bắt đầu. Sử dụng truy vấn thông minh hơn mà không nhân các hàng cơ sở, sau đó bạn không phải tổng hợp chúng lại.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tối ưu hóa truy vấn trong PostgreSQL. GIẢI THÍCH Khái niệm cơ bản - Phần 3

  2. Có gì mới trong Postgres-XL 9.6

  3. Làm thế nào để bạn xác định các hàm postgres trong Rails và phạm vi cũng như thời gian tồn tại của chúng là gì?

  4. So sánh các bảng tạm thời cho PostgreSQL và Oracle GTT

  5. Hiểu dàn diễn viên từ bytea đến oid