2016-11-17 272 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