postgresql 如何按顺序聚合行?

56lgkhnf  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(140)

我有这样的疑问:

SELECT p.*, po.product_options
    FROM product p
    LEFT JOIN  (
        SELECT po.p_id, 
               json_agg(
                  json_build_object('id', po.id, 'name', po.name, 'options', pom.option_name)) AS product_options
        FROM product_options po
        INNER JOIN (
          SELECT product_options_id, json_agg(option_name) as option_name
          FROM product_options_value
          GROUP BY product_options_id
          ) pom ON pom.product_options_id = po.id
        GROUP BY p_id
    ) po ON po.p_id = p.id
WHERE p.id = 1;

字符串
这是一个db fiddle:
http://sqlfiddle.com/#!17/b47e3b/8
现在我想从表product_options中按列s_position对行进行排序。我得到:
错误:列“po.s_position”必须出现在GROUP BY子句中或在聚合函数中使用
但是如果我将列添加到GROUP BY中,我会得到2行而不是1行。我如何在表product_options中按s_position排序,以便仍然得到相同的结果,但具有有序的选项?

ffdz8vbo

ffdz8vbo1#

在子查询中按照p_id聚合来自product_options的所有行后,尝试按product_options.s_position排序将是不明确的。因此您看到了错误消息。
要按照s_position设置的顺序聚合product_options中的行,请执行以下操作:

SELECT *
FROM   product p
LEFT  JOIN (
   SELECT po.p_id AS id
        , json_agg(json_build_object('id', id, 'name', name, 'options', pom.option_name)
                   ORDER BY po.s_position) AS product_options  -- !
   FROM   product_options po
   JOIN  (
      SELECT product_options_id AS id, json_agg(option_name) AS option_name
      FROM   product_options_value
      GROUP  BY 1
      ) pom USING (id)
   GROUP  BY 1
   ) po USING (id)
WHERE  p.id = 1;

字符串
fiddle
或者,您可以在一个额外的子查询中对行进行排序,这样通常会更快。请参阅:

  • 如何根据对象的属性对json或jsonb值中的数组中的对象进行排序?

相关问题