【问题标题】:Postgresql jsonb_agg subquery sortPostgresql jsonb_agg 子查询排序
【发布时间】:2016-11-17 10:48:52
【问题描述】:

如何对使用 json 聚合的子查询的结果进行排序?

如果我有这样的架构:

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);

我正在通过子查询在 json 列上聚合 plan_items 结果。 像这样:

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

但这些都没有解决。

有什么想法吗?

【问题讨论】:

  • 尝试使用聚合的扩展形式:jsonb_agg(... order by plan_items.expected_at)

标签: json postgresql subquery


【解决方案1】:

正如Abelisto 建议的那样,只需使用简单的aggregate expression with ordering

jsonb_agg(plan_items ORDER BY plan_items.expected_at) AS plan_items_data

【讨论】:

    【解决方案2】:

    以所需的排序顺序连接表并使用横向连接为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;
    

    【讨论】:

    • 谢谢klin,但我认为这个查询不需要横向......看起来Abelisto的评论就足够了。 ?
    • 横向连接不是这里的特殊功能,它只是我更喜欢编写这样的查询的方式。当然,带有order by 子句的聚合是一个很好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    相关资源
    最近更新 更多