更新:PostgreSQL 9.4では、to_json
の導入により、これが大幅に改善されています。 、json_build_object
、json_object
およびjson_build_array
、ただし、すべてのフィールドに明示的に名前を付ける必要があるため、冗長です:
select
json_build_object(
'id', u.id,
'name', u.name,
'email', u.email,
'user_role_id', u.user_role_id,
'user_role', json_build_object(
'id', ur.id,
'name', ur.name,
'description', ur.description,
'duty_id', ur.duty_id,
'duty', json_build_object(
'id', d.id,
'name', d.name
)
)
)
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id;
古いバージョンについては、読み進めてください。
それは単一の行に限定されていません、それはほんの少し苦痛です。 AS
を使用して複合行タイプのエイリアスを作成することはできません 、したがって、効果を得るには、エイリアス化されたサブクエリ式またはCTEを使用する必要があります。
select row_to_json(row)
from (
select u.*, urd AS user_role
from users u
inner join (
select ur.*, d
from user_roles ur
inner join role_duties d on d.id = ur.duty_id
) urd(id,name,description,duty_id,duty) on urd.id = u.user_role_id
) row;
http://jsonprettyprint.com/経由で生成:
{
"id": 1,
"name": "Dan",
"email": "[email protected]",
"user_role_id": 1,
"user_role": {
"id": 1,
"name": "admin",
"description": "Administrative duties in the system",
"duty_id": 1,
"duty": {
"id": 1,
"name": "Script Execution"
}
}
}
array_to_json(array_agg(...))
を使用することをお勧めします 1:多くの関係がある場合、ところで。
上記のクエリは、理想的には次のように記述できる必要があります。
select row_to_json(
ROW(u.*, ROW(ur.*, d AS duty) AS user_role)
)
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id;
...しかしPostgreSQLのROW
コンストラクターはAS
を受け入れません 列エイリアス。悲しいことに。
ありがたいことに、彼らは同じように最適化します。計画を比較する:
- ネストされたサブクエリバージョン。 vs
- 後者のネストされた
ROW
実行するようにエイリアスが削除されたコンストラクタバージョン
CTEは最適化フェンスであるため、ネストされたサブクエリバージョンを言い換えて、チェーンCTE(WITH
)を使用します。 式)はうまく機能しない可能性があり、同じ計画にはなりません。この場合、row_to_json
にいくつかの改善が加えられるまで、ネストされた醜いサブクエリで立ち往生しています。 または、ROW
の列名を上書きする方法 コンストラクターをより直接的に。
とにかく、一般的に、原則は、列a, b, c
を持つjsonオブジェクトを作成する場合です。 、そしてあなたはあなたがただ違法な構文を書くことができたらいいのにと思います:
ROW(a, b, c) AS outername(name1, name2, name3)
代わりに、行タイプの値を返すスカラーサブクエリを使用できます:
(SELECT x FROM (SELECT a AS name1, b AS name2, c AS name3) x) AS outername
または:
(SELECT x FROM (SELECT a, b, c) AS x(name1, name2, name3)) AS outername
さらに、json
を作成できることを覚えておいてください 追加の引用符なしの値、例: json_agg
の出力を配置する場合 row_to_json
内 、内側のjson_agg
結果は文字列として引用されず、jsonとして直接組み込まれます。
例えば任意の例で:
SELECT row_to_json(
(SELECT x FROM (SELECT
1 AS k1,
2 AS k2,
(SELECT json_agg( (SELECT x FROM (SELECT 1 AS a, 2 AS b) x) )
FROM generate_series(1,2) ) AS k3
) x),
true
);
出力は次のとおりです。
{"k1":1,
"k2":2,
"k3":[{"a":1,"b":2},
{"a":1,"b":2}]}
json_agg
に注意してください product、[{"a":1,"b":2}, {"a":1,"b":2}]
、text
として、再度エスケープされていません
これは、作成できることを意味します 行を構築するためのjson操作では、必ずしも非常に複雑なPostgreSQL複合型を作成してから、row_to_json
を呼び出す必要はありません。 出力に。