如何将多个列分组为单个数组或类似数组?

2024-03-18

我希望我的查询返回这样的结构结果,其中tags是数组的数组或类似的数组:

id | name | tags
1    a      [[1, "name1", "color1"], [2, "name2", color2"]]
2    b      [[1, "name1", "color1"), (3, "name3", color3"]]

我期望这个查询能够工作,但它给了我一个错误:

SELECT  i.id, i.name, array_agg(t.tag_ids, t.tag_names, t.tag_colors) as tags 
FROM    ITEMS
LEFT OUTER JOIN (
  SELECT      trm.target_record_id
            , array_agg(tag_id) as tag_ids
            , array_agg(t.tag_name) as tag_names
            , array_agg(t.tag_color) as tag_colors
  FROM        tags_record_maps trm
  INNER JOIN  tags t on t.id = trm.tag_id
  GROUP BY    trm.target_record_id
) t on t.target_record_id = i.id;

Error:

PG::UndefinedFunction: ERROR:  function array_agg(integer[], character varying[], character varying[]) does not exist
LINE 1: ..., action_c2, action_c3, action_name, action_desc, array_agg(...
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

该查询有效并产生类似的结果(但不完全是我想要的):

SELECT  i.id, i.name, t.tag_ids, t.tag_names, t.tag_colors as tags  as tags 
FROM    ITEMS
LEFT OUTER JOIN (
  SELECT      trm.target_record_id, array_agg(tag_id) as tag_ids, array_agg(t.tag_name) as tag_names, array_agg(t.tag_color) as tag_colors
  FROM        tags_record_maps trm
  INNER JOIN  tags t on t.id = trm.tag_id
  GROUP BY    trm.target_record_id
) t on t.target_record_id = i.id;

Result:

id | name | tag_ids | tag_names         | tag_colors          
1    a      [1, 2]    ["name1, "name2"]   ["color1", "color2"]
1    a      [1, 3]    ["name1, "name3"]   ["color1", "color3"]

Edit:

这个查询几乎产生了我正在寻找的东西,除了它命名了 json 键f1, f2, f3。如果能说出他们的名字就完美了id, name, color:

  SELECT        trm.target_record_id, json_agg( (t.id, t.tag_name, t.tag_color) )
  FROM          tags_record_maps trm
  INNER JOIN    tags t on t.site_id = trm.site_id and t.id = trm.tag_id
  GROUP BY      trm.target_record_id
  having count(*) > 1;

Result:

[{"f1":1,"f2":"name1","f3":"color1"},{"f1":2,"f2":"name2","f3":"color2"}]

(t.id, t.tag_name, t.tag_color)是短语法ROW(t.id, t.tag_name, t.tag_color)- 和一个行构造函数 https://www.postgresql.org/docs/current/sql-expressions.html#SQL-SYNTAX-ROW-CONSTRUCTORS不保留嵌套属性名称。手册: https://www.postgresql.org/docs/current/sql-expressions.html#SQL-SYNTAX-ROW-CONSTRUCTORS

默认情况下,由 a 创建的值ROW表达式是一个匿名记录类型。如果需要,可以将其转换为命名复合类型 - 表的行类型,或者使用创建的复合类型CREATE TYPE AS.

大胆强调我的。为了在结果中获得正确的键名称,cast对于引用中建议的注册复合类型,请使用嵌套子选择,或者简单地使用json_build_object() https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-CREATION-TABLE在 Postgres 9.4 或更高版本中(有效地避免了 ROW 构造函数):

SELECT trm.target_record_id
     , json_agg(json_build_object('id', t.id
                                , 'tag_name', t.tag_name
                                , 'tag_color', t.tag_color)) AS tags
FROM   tags_record_maps trm
JOIN   tags             t USING (site_id)
WHERE  t.id = trm.tag_id
GROUP  BY trm.target_record_id
HAVING count(*) > 1;

我使用原始的列名称,但您可以自由选择键名称。在你的情况下:

       json_agg(json_build_object('id', t.id
                                , 'name', t.tag_name
                                , 'color', t.tag_color)) AS tags

详细解释:

  • 返回同一行的多列作为对象的 JSON 数组 https://stackoverflow.com/questions/26486784/return-multiple-columns-of-the-same-row-as-json-array-of-objects
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将多个列分组为单个数组或类似数组? 的相关文章

随机推荐