【问题标题】:Extract key, value from json objects in Postgres从 Postgres 中的 json 对象中提取键、值
【发布时间】:2016-12-24 22:27:53
【问题描述】:

我有一个 Postgres 表,其内容类似于:

id  | data

1   | {"a":"4", "b":"5"}
2   | {"a":"6", "b":"7"}
3   | {"a":"8", "b":"9"}

第一列是整数,第二列是json列。

我希望能够扩展 json 中的键和值,因此结果如下所示:

id  | key  | value

1   | a    | 4
1   | b    | 5
2   | a    | 6
2   | b    | 7
3   | a    | 8
3   | b    | 9

这可以在 Postgres SQL 中实现吗?


我的尝试

鉴于原始表格可以这样模拟:

select *
from 
(
values
(1, '{"a":"4", "b":"5"}'::json),
(2, '{"a":"6", "b":"7"}'::json),
(3, '{"a":"8", "b":"9"}'::json)
) as q (id, data)

我可以使用以下方法获取密钥:

select id, json_object_keys(data::json)
from 
(
values
(1, '{"a":"4", "b":"5"}'::json),
(2, '{"a":"6", "b":"7"}'::json),
(3, '{"a":"8", "b":"9"}'::json)
) as q (id, data)

我可以像这样将它们作为记录集获取:

select id, json_each(data::json)
from 
(
values
(1, '{"a":"4", "b":"5"}'::json),
(2, '{"a":"6", "b":"7"}'::json),
(3, '{"a":"8", "b":"9"}'::json)
) as q (id, data)

但我不知道如何通过 id、key 和 value 来实现结果。

有什么想法吗?

注意:我正在使用的真正的 json 比这更嵌套,但我认为这个例子很好地代表了我的潜在问题。

【问题讨论】:

标签: json postgresql jsonb


【解决方案1】:
SELECT q.id, d.key, d.value
FROM q
JOIN json_each_text(q.data) d ON true
ORDER BY 1, 2;

函数json_each_text() 是一个集合返回函数,因此您应该将它用作行源。函数的输出在这里是joined laterally 到表q,这意味着对于表中的每一行,来自data 列的每个(key, value) 对仅连接到该行,因此原始行之间的关系并维护由json 对象形成的行。

q 也可以是一个非常复杂的子查询(或VALUES 子句,就像你的问题一样)。在函数中,从评估该子查询的结果中使用适当的列,因此您仅使用对子查询的别名和子查询中的(的别名)列的引用。

【讨论】:

  • 谢谢帕特里克。我仍然对如何将其适应原始查询感到有些困惑。我是否使用“WITH”语句定义“q”?
  • 不用WITH语句能实现吗?
  • q 是您所指的表,您将其用作原始表的代理。
  • 嗯,好的。所以在我的真实示例中,实际上并没有一个表,而是一个名为 q 的内部查询。我想在那种情况下,一个 WITH 语句是唯一的方法? [附:我接受了你的回答]
  • 您可以使用任何一种,但 WITH 语句和子查询之间存在细微差别:第一个按指定处理,然后在主查询中使用,而子查询将“扁平化”,然后在处理之前合并到主查询中。这可能会产生重要的性能影响;有关详细说明,请参阅this excellent blog post by Craig Ringer
【解决方案2】:

这也将解决它:

select you_table.id , js.key, js.value
from you_table, json_each(you_table.data) as js

【讨论】:

    【解决方案3】:

    当您要加入多个 json 时,我认为另一种很容易工作的方法是:

    SELECT data -> 'key'   AS key, 
           data -> 'value' AS value 
    FROM   (SELECT Hstore(Json_each_text(data)) AS data 
            FROM   "your_table") t;
    

    【讨论】:

      猜你喜欢
      • 2019-02-05
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多