postgresql - 如何从 jsonb 返回对象数组?

标签 postgresql postgresql-9.4 jsonb

我有下表:

CREATE TABLE mytable (
  id       serial PRIMARY KEY
, employee text UNIQUE NOT NULL
, data     jsonb
);

具有以下数据:

INSERT INTO mytable (employee, data)
VALUES
 ('Jim', '{"sales_tv": [{"value": 10, "yr": "2010", "loc": "us"}, {"value": 5, "yr": "2011", "loc": "europe"}, {"value": 40, "yr": "2012", "loc": "asia"}], "sales_radio": [{"value": 11, "yr": "2010", "loc": "us"}, {"value": 8, "yr": "2011", "loc": "china"}, {"value": 76, "yr": "2012", "loc": "us"}], "another_key": "another value"}'),
 ('Rob', '{"sales_radio": [{"value": 7, "yr": "2014", "loc": "japan"}, {"value": 3, "yr": "2009", "loc": "us"}, {"value": 37, "yr": "2011", "loc": "us"}], "sales_tv": [{"value": 4, "yr": "2010", "loc": "us"}, {"value": 18, "yr": "2011", "loc": "europe"}, {"value": 28, "yr": "2012", "loc": "asia"}], "another_key": "another value"}')

请注意,除了“sales_tv”和“sales_radio”之外,还有其他键。对于下面的查询,我只需要关注“sales_tv”和“sales_radio”。

我正在尝试为 Jim 返回以“sales_”开头的任何对象的列表。在列表中的每个对象中,我只需要返回值和年份(忽略“位置”或任何其他键),例如:

    employee |  sales_
    Jim      |  {"sales_tv": [{"value": 10, "yr": "2010"}, {"value": 5, "yr": "2011"}, {"value": 40, "yr": "2012"}],
                 "sales_radio": [{"value": 11, "yr": "2010"}, {"value": 8, "yr": "2011"}, {"value": 76, "yr": "2012"}]}

我能够获取每个值,但没有年份,也没有我想要的列表格式:

SELECT t.employee, json_object_agg(a.k, d.value) AS sales
FROM   mytable t
     , jsonb_each(t.data)      a(k,v) 
     , jsonb_to_recordset(a.v) d(yr text, value float)
WHERE  t.employee = 'Jim'
AND    a.k LIKE 'sales_%'
GROUP  BY 1

结果:

employee    | sales
----------  | --------
Jim         | { "sales_tv" : 10, "sales_tv" : 5, "sales_tv" : 40, "sales_radio" : 11, "sales_radio" : 8, "sales_radio" : 76 }

最佳答案

原理同the question you asked yesterday ,第一个查询(即使这个问题是昨天的第二个查询):剥离 json 数据中的层次结构层,然后将它与您感兴趣的任何数据重新组合成任何新的 json 格式。

SELECT employee, json_object_agg(k, jarr) AS sales
FROM (
  SELECT t.employee, a.k,
         json_agg(json_build_object('value', d.value, 'yr', d.yr)) AS jarr
  FROM mytable t,
       jsonb_each(t.data) a(k, v),
       jsonb_to_recordset(a.v) d(yr text, value float)
  WHERE t.employee = 'Jim'
    AND a.k like 'sales_%'
  GROUP BY 1, 2) sub
GROUP BY 1; 

FROM 子句中,您使用 jsonb_eachjsonb_to_recordset 等函数分解 JSON 层次结构。正如最后一个函数的名称所暗示的那样,每个函数都会生成一组记录,您可以像处理任何其他表及其列一样使用这些记录。在列选择列表中,您选择所需的数据和适当的聚合函数 json_aggjson_object_agg 以将 JSON 结果拼凑起来。对于层次结构的每一层,您都需要一个聚合函数,因此需要一个子查询层。

关于postgresql - 如何从 jsonb 返回对象数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31573070/

相关文章:

postgresql - PostgreSQL 函数中是否有命名参数的约定

python - SqlAlchemy:查询 JSONB 字段中的对象数组

postgresql - 有没有办法以编程方式在 postgresql 中为 pk/fk 约束生成 CREATE 语句

postgresql - 如何在 Postgres 9.4 JSONB 列中执行不区分大小写的搜索?

arrays - jsonb 上的 Postgresql 数组交集

postgresql - postgres 9.2 中的 ROWID 等价物

sql - PostgreSQL - 如果所有列值为 'A' 或 NULL,我如何返回 ID

PostgreSQl pg_dump权限错误?

java - 在 PostgreSql 中批量更新或删除哪个更有效?

sql - Postgres : Querying multiple jsonb fields