在PostgreSQL中展平jsonb嵌套数组

时间:2018-06-28 06:14:22

标签: sql database postgresql

我在表中有一个数据

id(integer)    | label(text)     | value(jsonb)     |
---------------|-----------------|------------------|
12345          |       Education | [[{"label": "Type", "value": "Under Graduate"},{"label": "Location", "value": "New Delhi"}],[{"label": "Type", "value": "Post Graduate"}]]|

所需的输出是:

id    | label               | value          |
------|---------------------|----------------|
12345 | Education_Type_1    | Under Graduate |
12345 | Education_Location_1| New Delhi      |
12345 | Education_Type_2    | Post Graduate  |

有人可以帮我解决我面临的这个问题吗?

3 个答案:

答案 0 :(得分:1)

您可以使用jsonb_array_elements(your_jsonb_column)。在Postgres 9.6上测试。如果您使用其他版本,则可以使用json_array_elements(your_json_column)。

表格:

create table test (id int,label text, value jsonb);

插入声明:

insert into test values(12345,'Education','[[{"label": "Type", "value": "Under Graduate"}],[{"label": "Type", "value": "Post Graduate"}]]');
insert into test values(123456,'Education2','[[{"label": "Type2", "value": "Under Graduate2"}],[{"label": "Type2", "value": "Post Graduate2"}]]');

SQL查询:

select id, label,jsonb_array_elements(value)->0->>'value'
from test

其中0用于从数组中获取第一个元素。 ->>用于删除字符串中的引号。

输出:

id  label   value
12345   Education   Under Graduate
12345   Education   Post Graduate
123456  Education2  Under Graduate2
123456  Education2  Post Graduate2

SQL Fiddle

答案 1 :(得分:0)

我找到了解决方案。谢谢@Fahad Anjum。我将解决方案写在了您的灵魂之上。

SELECT 
    'Education_' || (jsonb_array_elements(elem)->>'label')::text || '_' || pos::text AS label, jsonb_array_elements(elem)->>'value'
FROM jsonb_array_elements(
    '{"test": [
        [{"label":"Type", "value": "Under Graduate"},{"label":"Location", "value": "New Delhi"},{"label":"CGPA", "value": "9.07"}],
        [{"label":"Type", "value": "Post Graduate"},{"label":"Location", "value": "Bangalore"}],
        [{"label":"Type", "value": "Some education 1"}]]}'::jsonb->'test'
    ) WITH ordinality arr(elem, pos);

答案 2 :(得分:0)

由于我们看重列就像不规则维的多维数组,因此我们将使用递归查询来查找解决方案。

在查询结果下方显示所需的必需输出

我已经在CTE中填充了您的示例数据。


    with recursive cte(id,label,value,dims) as (
     select
      12345,
      'Education'::text,
      '[
        [
         {"label": "Type", "value": "Under Graduate"},
         {"label": "Location", "value":"New Delhi"}
        ],
        [
         {"label": "Type", "value": "Post Graduate"}
        ]
       ]'::jsonb,
      jsonb_array_length('[[{"label": "Type", "value": "Under Graduate"},{"label": "Location", "value": "New Delhi"}],[{"label": "Type", "value": "Post Graduate"}]]'::jsonb)
    ), res(id,label,val,dims) as (
        select cte.id,cte.label,l.v,cte.dims-1
        from cte,lateral(
            select jsonb_array_elements(cte.value) as v
        ) l
        union all
        select
          res.id,res.label,l.v,res.dims-1
        from res,lateral(
           select jsonb_array_elements(res.val) as v
         ) l
        where
         res.dims>0
    )
    select
        res.id,
        res.val->>'value' as value,
        res.label ||
        '_'||
        (res.val->>'label')::text ||
        '_' ||
        row_number() over (partition by id,label,(res.val->>'label')::text) as label
    from res
    where dims=0