更新:在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 uinner join user_roles ur on ur.id = u.user_role_idinner 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://jsonbrush:php;toolbar:false.com/产生:
{ "id": 1, "name": "Dan", "email": "someemail@gmail.com", "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(...))一对一的关系,您将要使用,顺便说一句。
理想情况下,上面的查询应该可以编写为:
select row_to_json( ROW(u.*, ROW(ur.*, d AS duty) AS user_role))from users uinner join user_roles ur on ur.id = u.user_role_idinner join role_duties d on d.id = ur.duty_id;
…但是PostgreSQL的
ROW构造函数不接受
AS列别名。可悲的是。
值得庆幸的是,他们对它们进行了优化。比较计划:
- 该嵌套子查询的版本 ; 与
- 后者的嵌套
ROW
构造函数版本已删除别名,因此可以执行
由于CTE是优化屏障,因此将嵌套子查询版本改写为使用链接的CTE(
WITH表达式)可能效果不佳,并且不会得出相同的计划。在这种情况下,您会一直受困于丑陋的嵌套子查询,直到我们得到一些改进
row_to_json或
ROW更直接地覆盖构造函数中的列名的方法为止。
总之,总的来说,该原则是,您想在其中创建一个带有column的json对象
a, b, c,并且希望您可以编写非法语法:
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不附加引号的情况下编写值,例如,如果将a的输出放在
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产品
[{"a":1,"b":2}, {"a":1,"b":2}]不会再次转义,就像text那样。
这意味着您可以 组成 json操作来构造行,而不必总是创建非常复杂的PostgreSQL复合类型然后调用
row_to_json输出。



