Đ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 a1
và a2
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