136

名前を収集するために使用array_aggすると、名前をカンマで区切って取得しますが、null値がある場合、その null も集計内の名前として取得されます。例えば ​​:

SELECT g.id,
       array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users,
       array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users
FROM groups g
GROUP BY g.id;

,Larry,Philただの代わりに返されますLarry,Phil(私の9.1.2では、表示されますNULL,Larry,Phil)。

代わりに、 を使用するstring_agg()と、名前のみが表示されます (空のコンマやヌルなし)。

問題はPostgres 8.4、サーバーにインストールしたのに、string_agg()そこで動作しないことです。array_agg を string_agg() のように機能させる方法はありますか?

4

8 に答える 8

321

postgresql-9.3 ではこれを行うことができます。

SELECT g.id,
   array_remove(array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END), NULL) canonical_users,
   array_remove(array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END), NULL) non_canonical_users
FROM groups g 
GROUP BY g.id;

更新: postgresql-9.4; を使用。

SELECT g.id,
   array_agg(g.users) FILTER (WHERE g.canonical = 'Y') canonical_users,
   array_agg(g.users) FILTER (WHERE g.canonical = 'N') non_canonical_users
FROM groups g 
GROUP BY g.id;

更新 (2022-02-19) : postgresql-9.4 も使用。

配列内のすべての値が null の場合、null を返すのではなく、空の配列になります。

SELECT g.id,
  coalesce( array_agg(g.users) FILTER (WHERE g.canonical = 'Y'), '{}' ) canonical_users,
  coalesce( array_agg(g.users) FILTER (WHERE g.canonical = 'N'), '{}' ) non_canonical_users
FROM groups g 
GROUP BY g.id;
于 2014-04-14T02:17:54.593 に答える
38
select
    id,
    (select array_agg(a) from unnest(canonical_users) a where a is not null) canonical_users,
    (select array_agg(a) from unnest(non_canonical_users) a where a is not null) non_canonical_users
from (
    SELECT g.id,
           array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END) canonical_users,
           array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END) non_canonical_users
    FROM groups g
    GROUP BY g.id
) s

array_to_stringまたは、ヌルを排除する whichを使用して、よりシンプルで安価な場合があります。

SELECT
    g.id,
    array_to_string(
        array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END)
        , ','
    ) canonical_users,
    array_to_string(
        array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END)
        , ','
    ) non_canonical_users
FROM groups g
GROUP BY g.id
于 2012-10-29T14:11:24.563 に答える
3

コメントで提案されているように、配列内のヌルを置き換える関数を作成できますが、コメントでリンクされているスレッドでも指摘されているように、集計を作成する必要がある場合、この種の集計関数の効率が損なわれます、分割してから再度集約します。

配列にヌルを保持することは、Array_Agg の (おそらく望ましくない) 機能にすぎないと思います。これを回避するには、サブクエリを使用できます。

SELECT  COALESCE(y.ID, n.ID) ID,
        y.Users,
        n.Users
FROM    (   SELECT  g.ID, ARRAY_AGG(g.Users) AS Users
            FROM    Groups g
            WHERE   g.Canonical = 'Y'
            GROUP BY g.ID
        ) y
        FULL JOIN 
        (   SELECT  g.ID, ARRAY_AGG(g.Users) AS Users
            FROM    Groups g
            WHERE   g.Canonical = 'N'
            GROUP BY g.ID
        ) n
            ON n.ID = y.ID

SQL フィドル

于 2012-10-29T14:54:56.497 に答える
0

それは非常に簡単です。まず最初に、新しい- (マイナス)演算子をtext[]に作成します。

CREATE OR REPLACE FUNCTION diff_elements_text
    (
        text[], text[] 
    )
RETURNS text[] as 
$$
    SELECT array_agg(DISTINCT new_arr.elem)
    FROM
        unnest($1) as new_arr(elem)
        LEFT OUTER JOIN
        unnest($2) as old_arr(elem)
        ON new_arr.elem = old_arr.elem
    WHERE old_arr.elem IS NULL
$$ LANGUAGE SQL IMMUTABLE;

CREATE OPERATOR - (
    PROCEDURE = diff_elements_text,
    leftarg = text[],
    rightarg = text[]
);

そして、単純に配列[null]を減算します:

select 
    array_agg(x)-array['']
from
    (   select 'Y' x union all
        select null union all
        select 'N' union all
        select '' 
    ) x;

それで全部です:

{はい、いいえ}

于 2019-10-29T12:37:01.167 に答える