PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Przecięcie wielu tablic w PostgreSQL

Najbliższą rzeczą do przecięcia tablic jest to:

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

Zakłada się, że a1 i a2 to tablice jednowymiarowe z elementami tego samego typu. Możesz to ująć w funkcję podobną do tej:

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;

Wtedy możesz zrobić takie rzeczy:

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

Zauważ, że nie gwarantuje to żadnej konkretnej kolejności w zwróconej tablicy, ale możesz to naprawić, jeśli Ci na tym zależy. Następnie możesz utworzyć własną funkcję agregującą:

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

A teraz widzimy, dlaczego array_intersect robi zabawne i nieco niezdarne rzeczy z wartościami NULL. Potrzebujemy wartości początkowej dla agregacji, która zachowuje się jak zestaw uniwersalny i możemy do tego użyć wartości NULL (tak, to trochę brzydko pachnie, ale nie mogę wymyślić nic lepszego poza czubkiem głowy).

Gdy to wszystko będzie gotowe, możesz zrobić takie rzeczy:

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

Niezupełnie prosty lub wydajny, ale może rozsądny punkt wyjścia i lepszy niż nic.

Przydatne referencje:

  • array_agg
  • utwórz agregat
  • utwórz funkcję
  • 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. Wstaw obraz do bazy postgresql

  2. XMLTABLE w PostgreSQL

  3. Nowe dane nie są zachowywane w kolumnie tablicy Rails w Postgresie

  4. django.db.utils.ProgrammingError:relacja już istnieje

  5. Fluent NHibernate i PostgreSQL, SchemaMetadataUpdater.QuoteTableAndColumns — System.NotSupportedException:określona metoda nie jest obsługiwana