1. ホーム
  2. sql

[解決済み] postgresを使用してstring_aggのようにarray_aggでnull値を除外する方法は?

2022-06-11 20:28:42

質問

もし私が 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()と同様に動作させる方法はありますか?

どのように解決するのですか?

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 を使うことで、NULLを排除することができます。

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