2016-11-17 54 views
0

如何排序使用json聚合的子查询的结果?Postgresql jsonb_agg子查询排序

如果我有这样的一个模式:

CREATE TABLE plans(id integer NOT NULL, name character varying(255)); 
CREATE TABLE plan_items (id integer NOT NULL, plan_id integer NOT NULL, expected_at date, status integer); 

我聚集plan_items通过一个子查询JSON列结果。 像这样:

SELECT 
    plans.id, 
    plans.name, 
    jsonb_agg((SELECT pi_cols FROM 
     (SELECT plan_items.id, plan_items.expected_at, plan_items.status) pi_cols 
    )) AS plan_items_data 
FROM 
    plans 
    INNER JOIN plan_items ON plan_items.plan_id = plans.id 
GROUP BY 
    plans.id, 
    plans.name 
ORDER BY plans.id; 

的JSON总工作正常,给我我需要的结果。好。 但我不能订购结果。

我已经试过:

jsonb_agg((SELECT pi_cols FROM 
     (SELECT plan_items.id, plan_items.expected_at, plan_items.status ORDER BY plan_items.expected_at) pi_cols 
    )) AS plan_items_data 

也:

jsonb_agg((SELECT pi_cols FROM 
     (SELECT plan_items.id, plan_items.expected_at, plan_items.status) pi_cols ORDER BY pi_cols.expected_at 
    )) AS plan_items_data 

但这些都不解决。

任何想法?

+1

尝试使用的骨料的扩展形式:'jsonb_agg(... ORDER BY plan_items.expected_at)' – Abelisto

回答

1

加入与所期望的排序顺序表和横向使用加入到选择jsonb_agg()列:

select s.plan_id id, name, jsonb_agg(pi_col) 
from (
    select p.id plan_id, p.name, pi.id, expected_at, status 
    from plans p 
    join plan_items pi 
    on p.id = pi.plan_id 
    order by p.id, expected_at 
    ) s, 
lateral (
    select plan_id id, expected_at, status 
    ) pi_col 
group by 1, 2 
order by 1; 

上面的查询似乎更加自然和灵活(并且在大多数情况下,快一点),比一个在选择列表中具有子查询。但是有更好的表现,你应该也适用Abelisto的建议:

select s.plan_id id, name, json_agg(pi_col order by pi_col.expected_at) 
from (
    select p.id plan_id, p.name, pi.id, expected_at, status 
    from plans p 
    join plan_items pi 
    on p.id = pi.plan_id 
    ) s, 
lateral (
    select plan_id id, expected_at, status 
    ) pi_col 
group by 1, 2 
order by 1; 
+0

感谢克林,但我不认为在这个查询中需要侧向...看起来Abelisto的评论就够了。 – AndreDurao

+0

侧向连接在这里不是一个特殊的功能,它只是我喜欢写这样的查询的方式。当然,使用'order by'子句的聚合是一个很好的解决方案。 – klin