我有一个像这样的表:
CREATE TABLE myrecord AS
id INT
other TEXT
attributes JSONB
属性的结构如下:
[
{"name": "a", "value": "1"},
{"name": "b", "value": "2"}
]
我想将其转换为如下结果:
id INT, other TEXT, a TEXT, b TEXT
这样对于给定的一行
1 | "foo" | {..as above..}
我得到这样的结果
1 | "foo" | "1" | "2"
现在我可以像这样解压属性结构:
CREATE TYPE myrecord_attributes AS (name TEXT, value TEXT);
SELECT
id,
other,
(json_populate_recordset(NULL :: myrecord_attributes,
attributes :: JSON)).*
FROM myrecord
但是这样我得到的结果如下:
1 | "foo" | "a" | "1"
1 | "foo" | "b" | "2"
如何将 json_populate_recordset
的结果扁平化为适当的结构?我也愿意接受根本不使用它的替代解决方案。
如果重要的话,我正在使用 postgres 9.4
最佳答案
你可以这样做:
select m.id,
m.other,
x.value::jsonb->>'name' as name,
x.value::jsonb->>'value' as value
from myrecord m,
json_array_elements(m.attributes) x;
如果您希望它返回带双引号的值,只需将 ->>
更改为 ->
在这里查看它的工作情况:http://sqlfiddle.com/#!15/450cc/9
这是利用隐式 LATERAL JOIN
在 Postgres 9.3 或更高版本中。
编辑
我的第一个解决方案不符合 OP 的要求,因此,我创建了另一个解决方案:
select m.id,
m.other,
max(case when x.value::json->>'name' = 'a'
then x.value::json->>'value' else '' end) as a,
max(case when x.value::json->>'name' = 'b'
then x.value::json->>'value' else '' end) as b
from myrecord m,
json_array_elements(m.attributes) x
group by m.id,
m.other;
在这里查看它的工作情况:http://sqlfiddle.com/#!15/450cc/14
关于json - 将json结构转换为行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36222954/