PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Пресичане на множество масиви в PostgreSQL

Най-близкото нещо до пресичане на масиви, за което се сещам, е това:

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

Това предполага, че a1 и a2 са едномерни масиви със същия тип елементи. Можете да увиете това във функция, подобна на това:

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;

Тогава можете да правите неща като това:

=> 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)

Имайте предвид, че това не гарантира конкретен ред в върнатия масив, но можете да поправите това, ако ви е грижа за него. След това можете да създадете своя собствена агрегатна функция:

-- 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[]
);

И сега виждаме защо array_intersect прави смешни и донякъде тъпи неща с NULL. Нуждаем се от първоначална стойност за агрегацията, която се държи като универсалния набор и можем да използваме NULL за това (да, това мирише малко на неудобство, но не мога да измисля нищо по-добро от главата си).

След като всичко това е на място, можете да правите неща като това:

> 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)

Не съвсем просто или ефективно, но може би е разумна отправна точка и по-добре от нищо.

Полезни препратки:

  • array_agg
  • създайте агрегат
  • функция за създаване
  • 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. Как да използвам схеми в Django?

  2. Как да експортирате таблица като CSV със заглавия на Postgresql?

  3. Нечувствителни ли са имената на функциите в PostgreSQL?

  4. Сортирайте NULL стойности в края на таблица

  5. Postgresql :Как да избера първите n процента(%) записи от всяка група/категория