【问题标题】:Extract into multiple columns from JSON with PostgreSQL使用 PostgreSQL 从 JSON 中提取多列
【发布时间】:2020-10-08 10:11:56
【问题描述】:

我有一列 item_id 包含 JSON(比如?)结构中的数据。

+----------+---------------------------------------------------------------------------------------------------------------------------------------+
|     id   |                                                                item_id                                                                |
+----------+---------------------------------------------------------------------------------------------------------------------------------------+
|    56711 | {itemID":["0530#2#1974","0538\/2#2#1974","0538\/3#2#1974","0538\/18#2#1974","0539#2#1974"]}"                                          |
|    56712 | {itemID":["0138528#2#4221","0138529#2#4221","0138530#2#4221","0138539#2#4221","0118623\/2#2#4220"]}"                                  |
|    56721 | {itemID":["2704\/1#1#1356"]}"                                                                                                         |
|    56722 | {itemID":["0825\/2#2#3349","0840#2#3349","0844\/10#2#3349","0844\/11#2#3349","0844\/13#2#3349","0844\/14#2#3349","0844\/15#2#3349"]}" |
|    57638 | {itemID":["0161\/1#2#3364","0162\/1#2#3364","0163\/2#2#3364"]}"                                                                       |
|    57638 | {itemID":["109#1#3364","110\/1#1#3364"]}"                                                                                             |
+----------+---------------------------------------------------------------------------------------------------------------------------------------+

我需要每个逗号之前的最后四位数字(如果有),最后 4 位数字被区分并分成单独的列。
id 也应该发生不同的情况,因此只允许一个 id 为 57638 的结果行。

这是一个fiddle,其中的代码草稿没有给出正确的答案。 期望的结果应该是这样的:

+----------+-----------+-----------+
|    id    | item_id_1 | item_id_2 |
+----------+-----------+-----------+
|    56711 |      1974 |           |
|    56712 |      4220 |      4221 |
|    56721 |      1356 |           |
|    56722 |      3349 |           |
|    57638 |      3364 |      3365 |
+----------+-----------+-----------+

结果中可能有很多 'item_id_%' 列。

【问题讨论】:

标签: arrays json postgresql select postgresql-9.6


【解决方案1】:
with the_table (id, item_id) as (
values
(56711, '{"itemID":["0530#2#1974","0538\/2#2#1974","0538\/3#2#1974","0538\/18#2#1974","0539#2#1974"]}'),
(56712, '{"itemID":["0138528#2#4221","0138529#2#4221","0138530#2#4221","0138539#2#4221","0118623\/2#2#4220"]}'),
(56721, '{"itemID":["2704\/1#1#1356"]}'),
(56722, '{"itemID":["0825\/2#2#3349","0840#2#3349","0844\/10#2#3349","0844\/11#2#3349","0844\/13#2#3349","0844\/14#2#3349","0844\/15#2#3349"]}'),
(57638, '{"itemID":["0161\/1#2#3364","0162\/1#2#3364","0163\/2#2#3364"]}'),
(57638, '{"itemID":["109#1#3365","110\/1#1#3365"]}')
)
select id
    ,(array_agg(itemid)) [1] itemid_1
    ,(array_agg(itemid)) [2] itemid_2
from (
    select distinct id
        ,split_part(replace(json_array_elements(item_id::json -> 'itemID')::text, '"', ''), '#', 3)::int itemid
    from the_table
    order by 1
        ,2
    ) t
group by id

DEMO

【讨论】:

    【解决方案2】:

    你可以对json数组进行unnest,获取每个元素的最后4个字符作为数字,然后进行条件聚合:

    select 
        id,
        max(val) filter(where rn = 1) item_id_1,
        max(val) filter(where rn = 2) item_id_2
    from (
        select
            id,
            right(val, 4)::int val,
            dense_rank() over(partition by id order by right(val, 4)::int) rn
        from mytable t
        cross join lateral jsonb_array_elements_text(t.item_id -> 'itemID') as x(val)
    ) t
    group by id
    

    您可以在外部查询中添加更多条件max()s 以处理更多可能的值。

    Demo on DB Fiddle

    编号 | item_id_1 | item_id_1 ----: | --------: | --------: 56711 | 1974 | 56712 | 4220 | 4221 56721 |第1356章 56722 |第3349章 57638 |第3364章3365

    【讨论】:

      猜你喜欢
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-24
      • 1970-01-01
      • 2017-02-11
      • 1970-01-01
      • 2017-06-23
      相关资源
      最近更新 更多