The tables in the query are not designed or controlled by me. Please don't tell me to change the table structure because it is outside my scope. using "PostgreSQL 11.16 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 7.3.1 20180712 (Red Hat 7.3.1-12), 64-bit"
This is a snippet of the table structure. All json is stored as character varying. This is one column in the table. For this exercise, just call the table "ThisTable" and the column "Brands".
[
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "101B_xx20048TS5M_113"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "50499_PR2051TGY_211"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "931002492_GHJ120044VDA22_321"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "4023451_JK49880RWD_521"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "71093129_PR3225TGY_211"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "71093419_PR3225TGY_211"
}
]
the goal is to find a particular site (upper level in the nesting- example "https://brand.map.com/cur") for a particular code and system in the nested type/coding structure. (example is code "gee" for site "http://ag.org/clear/latest/green-fld/Coding/GrType" for the Brands column.
this could be used in either a select or a where clause (e.g. need to display it and/or use it as selection criteria)
I can break out the Brands column and get the type and/or coding, but I am failing to see how to break out the coding array. I've been using a cross join. This shows a way to break out the details but fails if I try to add the site type array.
from ThisTable TT
cross join jsonb_array_elements(TT.Brands::jsonb) as ttb(site_arr)
--cross join jsonb_array_elements(ttb.site_arr->>'type') as ttbs(sitetype_arr)
I can work around this but mostly want to understand. This is the selection I need to make (I think) but I can't select type or coding to extract this and then cross join. I'm not sure if unnest is a better option. I could not get json_path_query to work in this case.
SELECT brandtype->>'code' as brand_type_code
FROM jsonb_array_elements('[
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]') as brandtype
CodePudding user response:
Maybe this will helped you. If you need anything else, let me, I will explain or help.
with table1 as (
select
'[
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "101B_xx20048TS5M_113"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "50499_PR2051TGY_211"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "931002492_GHJ120044VDA22_321"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "4023451_JK49880RWD_521"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "71093129_PR3225TGY_211"
},
{
"site": "https://brand.map.com/cur",
"type": {
"coding": [
{
"code": "gee",
"display": "Green Field",
"site": "http://ag.org/clear/latest/green-fld/Coding/GrType",
"version": "1.0.0"
}
]
},
"value": "71093419_PR3225TGY_211"
}
]'::jsonb as datajson)
select
table2->>'site',
table2->>'value',
table2->'type'->'coding'->0->>'code',
table2->'type'->'coding'->0->>'display',
table2->'type'->'coding'->0->>'version'
from table1
cross join jsonb_array_elements(table1.datajson) as table2
Result:
https://brand.map.com/cur 101B_xx20048TS5M_113 gee Green Field 1.0.0
https://brand.map.com/cur 50499_PR2051TGY_211 gee Green Field 1.0.0
https://brand.map.com/cur 931002492_GHJ120044VDA22_321 gee Green Field 1.0.0
https://brand.map.com/cur 4023451_JK49880RWD_521 gee Green Field 1.0.0
https://brand.map.com/cur 71093129_PR3225TGY_211 gee Green Field 1.0.0
https://brand.map.com/cur 71093419_PR3225TGY_211 gee Green Field 1.0.0
CodePudding user response:
If I recapitulate what you are doing by filling in the missing pieces and then uncommenting the commented out jsonb_array_elements I get this error:
ERROR: function jsonb_array_elements(text) does not exist
LINE 3: cross join jsonb_array_elements(ttb.site_arr->>'type') as tt...
(But you should show the error yourself, not make us re-discover it.) And the reason for this error is that ->>
yields text, not jsonb. If I switch it to ->
to preserve the type as jsonb, then I get a different error:
ERROR: cannot extract elements from an object
Which is because ->'type'
on your data yields an object, not an array. You can pull the array out of that object by adding one more level of referencing, so:
select sitetype_arr from ThisTable TT
cross join jsonb_array_elements(TT.Brands::jsonb) as ttb(site_arr)
cross join jsonb_array_elements(ttb.site_arr->'type'->'coding') as ttbs(sitetype_arr);
Now this does work. It yields the same thing 6 times, but that is because your data just has the same thing repeated 6 times; there is nothing we can do about your data being silly.