The JSON object contains a nested array of objects:
DECLARE @json NVARCHAR(MAX) =
'{
"productId": "508634800",
"description": "Generic description",
"itemInfo": [
{
"sku": "4645309",
"attributes": [
{
"attrName": "Size",
"attrValue": "M"
},
{
"attrName": "Color",
"attrValue": "Burgundy"
}
]
},
{
"sku": "4645318",
"attributes": [
{
"attrName": "Size",
"attrValue": "XL"
},
{
"attrName": "Color",
"attrValue": "Burgundy"
}
]
},
{
"sku": "4645400",
"attributes": [
{
"attrName": "Size",
"attrValue": "L"
},
{
"attrName": "Color",
"attrValue": "White"
}
]
}
]
}'
I would like to get the full list of matching pairs:
color size
----------------- -----------------
Burgundy M
Burgundy XL
White L
The problem that I'm hitting is that the only way I seem to be able to parse inside an array is to use OPENJSON, and I can't nest those calls.
The best solution I've come up with is to grab the first array, dump it to a temp table, then I can use CROSS APPLY to pull the data back out:
SELECT
@json = attributes
FROM
OPENJSON(@json)
WITH (
attributes NVARCHAR(MAX) '$.itemInfo' AS JSON
)
SELECT
row = ROW_NUMBER() OVER (ORDER BY attributes)
, attributes
INTO
#tempAttributes
FROM
OPENJSON(@json)
WITH (
attributes NVARCHAR(MAX) '$.attributes' AS JSON
)
SELECT DISTINCT
color = color.attrValue
, size = size.attrValue
FROM
#tempAttributes
CROSS APPLY OPENJSON(attributes)
WITH (
attrName NVARCHAR(MAX) '$.attrName'
, attrValue NVARCHAR(MAX) '$.attrValue'
) color
CROSS APPLY OPENJSON(attributes)
WITH (
attrName NVARCHAR(MAX) '$.attrName'
, attrValue NVARCHAR(MAX) '$.attrValue'
) size
WHERE
size.attrName = 'Size'
AND color.attrName = 'Color'
This works, but it feels necessarily complicated- is there a simpler way to get the results without jumping through so many hoops?
DB Fiddle here: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=b837e4e060744cddbd56c8f2f57b720a