sql >> Databáze >  >> RDS >> PostgreSQL

Průnik více polí v PostgreSQL

Nejbližší věc k průsečíku pole, která mě napadá, je toto:

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

To předpokládá, že a1 a a2 jsou jednorozměrná pole se stejným typem prvků. Můžete to zabalit do funkce, která je podobná této:

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;

Pak byste mohli dělat věci jako toto:

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

Všimněte si, že to nezaručuje žádné konkrétní pořadí ve vráceném poli, ale můžete to opravit, pokud vám na tom záleží. Pak byste mohli vytvořit svou vlastní agregační funkci:

-- 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 nyní vidíme, proč array_intersect dělá legrační a poněkud nemotorné věci s NULL. Potřebujeme počáteční hodnotu pro agregaci, která se chová jako univerzální množina, a na to můžeme použít NULL (ano, trochu to zavání, ale nic lepšího mě z hlavy nenapadá).

Jakmile je toto vše na místě, můžete dělat věci jako:

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

Není to úplně jednoduché nebo efektivní, ale možná je to rozumný výchozí bod a lepší než nic.

Užitečné odkazy:

  • array_agg
  • vytvořit souhrn
  • vytvořit funkci
  • PL/pgSQL
  • unnest


  1. Jak se připojit k MySQL pomocí Pythonu

  2. Jak získat aktuální čas v SQLite

  3. SQL BETWEEN Operátor pro začátečníky

  4. textové vyhledávání objektů Oracle