The discussed problem has been solved partly in here: Read in nested JSON file in SQL Server
but now the JSON file was extended with more objects of different format.
Declare @json nvarchar(max)
SELECT @json =
N'{
"Model": {
"Energy-X/A": {
"x": 1,
"y": 2,
"z": 3
},
"Energy-X/B": {
"x": 4,
"y": 5,
"z": 6
}
},
"Energy":
{
"Energy-X/A": [
[
100.123456, null
],
[
101.123456, null
]
],
"Energy-X/B": [
[
102.123456, null
],
[
103.123456, null
]
]
}
}'
select * from openjson(@json, '$.Model')
with (x [int] '$."Energy-X/A".x',
y [int] '$."Energy-X/A".y',
z [int] '$."Energy-X/A".z',
x [int] '$."Energy-X/B".x',
y [int] '$."Energy-X/B".y',
z [int] '$."Energy-X/B".z'
);
select commaDelimited.* from openjson (@json)
with (energyXA nvarchar(max) '$.Energy."Energy-X/A"' as json,
energyXB nvarchar(max) '$.Energy."Energy-X/B"' as json
) as energy
cross apply (
select
(select string_agg(isnull(value, 'null'), ',') from openjson(energyXA, '$[0]')),
(select string_agg(isnull(value, 'null'), ',') from openjson(energyXB, '$[0]'))
union all
select
(select string_agg(isnull(value, 'null'), ',') from openjson(energyXA, '$[1]')),
(select string_agg(isnull(value, 'null'), ',') from openjson(energyXB, '$[1]'))
) commaDelimited ([Energy-X/A], [Energy-X/B]);
The solution works and the values can be extracted but now I want to combine both SELECT statements into one query and construct a correlated subquery. The columns should appear when "Energy-X/A" and Energy-X/B" match like:
Energy-X/A | Energy-X/A | x | y | z |
---|---|---|---|---|
100.123456, null | 101.123456, null | 1 | 2 | 3 |
Energy-X/B | Energy-X/B | x | y | z |
---|---|---|---|---|
102.123456, null | 103.123456, null | 4 | 5 | 6 |
or also better output would be to sum up the values of Energy-X/A
and Energy-X/B
in one, separate column (using a delimiter such as semicolon):
Energy-X/A | x | y | z |
---|---|---|---|
100.123456, null ; 101.123456, null | 1 | 2 | 3 |
Energy-X/B | x | y | z |
---|---|---|---|
102.123456, null ; 103.123456, null | 1 | 2 | 3 |
I am grateful for any help!
CodePudding user response:
Since you changed your expected results significantly, I've completely re-written your query.
Start by unpivoting the A and B values into separate rows using a (values)
table and json_query
.
Then read those columns using openjson
.
In the case of Energy
you need two levels of aggregation also, in order to get your second expected result.
select
commaDelimited.*,
model.*
from (values
(json_query(@json, '$.Model.BCS'), json_query(@json, '$.Energy."Energy-X/A"')),
(json_query(@json, '$.Model.BCSA'), json_query(@json, '$.Energy."Energy-X/B"'))
) j(model, energy)
outer apply openjson(j.model)
with (
x int,
y int,
z int
) model
outer apply (
select
Energy = string_agg(c.Energy, ' ; ')
from openjson(j.energy) energy
cross apply (
select
Energy = string_agg(isnull(Xinner.value, 'null'), ', ')
from openjson(energy.value) Xinner
) c
) commaDelimited;