sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLでの複数の配列の交差

    私が考えることができる配列交差点に最も近いものはこれです:

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

    これは、a1が およびa2 同じタイプの要素を持つ1次元配列です。これを次のような関数にまとめることができます:

    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. INSERT ... ON DUPLICATE KEY(何もしない)

    2. テーブルが変化しているため、トリガー/関数に表示されない場合があります(平均グレードが2.5を下回るのを防ぐ)

    3. SQLDeveloperアイコン

    4. MySQLトリガーの使用