16

PostgreSQLで特定の結果をJSONとしてフォーマットするためarray_to_jsonにと組み合わせて使用​​しています。array_aggこれは、クエリのデフォルト値(すべての列、変更されていない)を返したい場合のクエリで正常に機能します。array_aggしかし、出力の一部を変更したいクエリのJSONオブジェクトを作成するためにどのように使用できるか困惑しています。

次に例を示します。

CREATE TABLE temp_user ( 
   user_id  serial PRIMARY KEY,
   real_name text
);
CREATE TABLE temp_user_ip (
   user_id  integer,
   ip_address text
);
INSERT INTO temp_user (user_id, real_name) VALUES (1, 'Elise'),  (2, 'John'), (3, NULL);
INSERT INTO temp_user_ip (user_id, ip_address) VALUES (1, '10.0.0.4'),  (2, '10.0.0.7'), (3, '10.0.0.9');

次のクエリは正常に機能します。

# SELECT array_to_json(array_agg(temp_user)) as users from temp_user;
                                            users                                                
-----------------------------------------------------------------------------------------------------
 [{"user_id":1,"real_name":"Elise"},{"user_id":2,"real_name":"John"},{"user_id":3,"real_name":null}]

しかし、ユーザー3にnull値が表示されるのが気に入らないとしましょう。代わりに、「ユーザーは$ipからログインしました」という文字列を表示したいと思います。

私がすることができます:

# SELECT user_id, (CASE WHEN real_name IS NULL THEN (select 'User logged in from ' || ip_address FROM temp_user_ip WHERE user_id = temp_user.user_id) ELSE real_name END) as name from temp_user;

そして、私は次の結果を得る:

 user_id |             name             
---------+------------------------------
       1 | Elise
       2 | John
       3 | User logged in from 10.0.0.9

これは素晴らしいことです。しかし、最初の例のように、このデータをJSON形式に操作する方法がわかりません。

必要な出力は次のとおりです。

[{"user_id":1,"name":"Elise"},{"user_id":2,"name":"John"},{"user_id":3,"name":"User logged in from 10.0.0.9"}]

これは機能しません:

# select array_to_json(array_agg ( (SELECT user_id, (CASE WHEN real_name IS NULL THEN (select 'User logged in from ' || ip_address FROM temp_user_ip WHERE user_id = temp_user.user_id) ELSE real_name END) as name from temp_user)));
ERROR:  subquery must return only one column

array_aggデータを受け入れる形式に変換する方法がわかりません。temp_userの形式に一致するカスタム型を作成array_aggし、型コンストラクターを呼び出そうとすると、同じエラーが返されました。エラーは私には意味がありません-サブクエリが集約されている場合、それが複数の列を返すかどうかは問題ではありません。何かアドバイス?

4

2 に答える 2

24

集約呼び出しをサブクエリから分離し、rowコンストラクターを使用して複合データを生成できます。

SELECT 
    array_to_json(array_agg(row(t.*))) AS users 
FROM 
    (
        SELECT user_id, 
            CASE 
                WHEN real_name IS NULL 
                THEN (
                    SELECT 'User logged in from ' || ip_address 
                    FROM temp_user_ip 
                    WHERE user_id = temp_user.user_id
                ) ELSE real_name 
            END AS name 
        FROM temp_user
    ) t
;

これはSQLFiddleでも確認できます。

于 2012-12-11T14:08:49.540 に答える
10

PostgreSQLにはjson_agg、代わりに使用できる機能がありますがarray_to_json(array_agg( ... ))、実際には、場合によってはより適切に動作します。「postgresのArray_aggは選択的に引用符で囲まれています」およびドキュメント「集計関数」を参照してください。

変更されたクエリは次のとおりです。

SELECT 
    json_agg(row(t.*)) AS users 
FROM 
    (
        SELECT user_id, 
            CASE 
                WHEN real_name IS NULL 
                THEN (
                    SELECT 'User logged in from ' || ip_address 
                    FROM temp_user_ip 
                    WHERE user_id = temp_user.user_id
                ) ELSE real_name 
            END AS name 
        FROM temp_user
    ) t
;
于 2017-04-26T15:07:42.453 に答える