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

Giao điểm của nhiều mảng trong PostgreSQL

Điều gần nhất với giao điểm mảng mà tôi có thể nghĩ đến là:

select array_agg(e)
from (
    select unnest(a1)
    intersect
    select unnest(a2)
) as dt(e)

Điều này giả định rằng a1a2 là các mảng một chiều có cùng loại phần tử. Bạn có thể gói gọn điều đó trong một chức năng như sau:

create function array_intersect(a1 int[], a2 int[]) returns int[] as $$
declare
    ret int[];
begin
    -- The reason for the kludgy NULL handling comes later.
    if a1 is null then
        return a2;
    elseif a2 is null then
        return a1;
    end if;
    select array_agg(e) into ret
    from (
        select unnest(a1)
        intersect
        select unnest(a2)
    ) as dt(e);
    return ret;
end;
$$ language plpgsql;

Sau đó, bạn có thể làm những việc như sau:

=> select array_intersect(ARRAY[2,4,6,8,10], ARRAY[1,2,3,4,5,6,7,8,9,10]);
 array_intersect 
-----------------
 {6,2,4,10,8}
(1 row)

Lưu ý rằng điều này không đảm bảo bất kỳ thứ tự cụ thể nào trong mảng được trả về nhưng bạn có thể khắc phục điều đó nếu bạn quan tâm đến nó. Sau đó, bạn có thể tạo hàm tổng hợp của riêng mình:

-- Pre-9.1
create aggregate array_intersect_agg(
    sfunc    = array_intersect,
    basetype = int[],
    stype    = int[],
    initcond = NULL
);

-- 9.1+ (AFAIK, I don't have 9.1 handy at the moment
-- see the comments below.
create aggregate array_intersect_agg(int[]) (
    sfunc = array_intersect,
    stype = int[]
);

Và bây giờ chúng ta thấy tại sao array_intersect làm những điều hài hước và có phần kỳ cục với NULL. Chúng tôi cần một giá trị ban đầu cho tập hợp hoạt động giống như tập hợp phổ quát và chúng tôi có thể sử dụng NULL cho điều đó (vâng, điều này hơi khó hiểu nhưng tôi không thể nghĩ ra điều gì tốt hơn ngoài đầu mình).

Khi tất cả điều này đã sẵn sàng, bạn có thể làm những việc như sau:

> select * from stuff;
    a    
---------
 {1,2,3}
 {1,2,3}
 {3,4,5}
(3 rows)

> select array_intersect_agg(a) from stuff;
 array_intersect_agg 
---------------------
 {3}
(1 row)

Không chính xác là đơn giản hay hiệu quả nhưng có thể là một điểm khởi đầu hợp lý và tốt hơn là không có gì cả.

Tham khảo hữu ích:

  • array_agg
  • tạo tổng hợp
  • tạo chức năng
  • PL / pgSQL
  • unnest


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nhận xét ký tự / ký tự trong postgres / postgresql / psql?

  2. Cách thay đổi người dùng thành Superuser trong PostgreSQL

  3. Các chuỗi không bị ảnh hưởng bởi các giao dịch?

  4. Tính tuổi theo năm trong PostgreSQL

  5. Câu lệnh sql với đệ quy được diễn giải như thế nào?