1

I have a column item_id that contains data in JSON (like?) structure.

+----------+---------------------------------------------------------------------------------------------------------------------------------------+
|     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"]}"                                                                                             |
+----------+---------------------------------------------------------------------------------------------------------------------------------------+

I need the last four digits before every comma (if there is) and the last 4 digits distincted and separated into individual colums.
The distinct should happen across id as well, so only one result row with id: 57638 is permitted.

Here is a fiddle with a code draft that is not giving the right answer. The desired result should look like this:

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

There can be quite a lot 'item_id_%' column in the results.

1
  • 1
    Since you can't select columns dynamically (you don't know how many item_id_X will be ) I think you should be using unpivot/pivot , see sample here stackoverflow.com/questions/14590859/… Commented Jun 18, 2020 at 11:25

2 Answers 2

0
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

Sign up to request clarification or add additional context in comments.

Comments

0

You can unnest the json array, get the last 4 characters of each element as a number, then do conditional aggregation:

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

You can add more conditional max()s to the outer query to handle more possible values.

Demo on DB Fiddle:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.