I am trying to convert a JSON object with "keys" as columns and each value in the list as a row.
I have managed to create the table structure I want, however I am getting the wrong number of rows.
DECLARE @result NVARCHAR(MAX) = N'{"foo": [101, 202, 303], "bar": [1,2,3], "test": [10,20,30], "input": [100,200,300]}'
SELECT
foo.value AS foo,
bar.value AS bar,
test.value AS test,
input.value AS input
FROM
OPENJSON(@result)
WITH (
foo NVARCHAR(MAX) '$.foo' AS JSON,
bar NVARCHAR(MAX) '$.bar' AS JSON,
test NVARCHAR(MAX) '$.test' AS JSON,
input NVARCHAR(MAX) '$.input' AS JSON
) AS json
CROSS APPLY OPENJSON(foo) AS foo
CROSS APPLY OPENJSON(bar) AS bar
CROSS APPLY OPENJSON(test) AS test
CROSS APPLY OPENJSON(input) AS input
This outputs 81 rows of this data:
foo | bar | test | input |
---|---|---|---|
101 | 1 | 10 | 100 |
101 | 1 | 10 | 100 |
202 | 2 | 20 | 200 |
202 | 2 | 20 | 200 |
303 | 3 | 30 | 300 |
303 | 3 | 30 | 300 |
x 27 rows each for 101 202 and 303 column rows values respectively
I want it to return rows that are length of the values in the list which would be 3 rows in this case:
Expected:
foo | bar | test | input |
---|---|---|---|
101 | 1 | 10 | 100 |
202 | 2 | 20 | 200 |
303 | 3 | 30 | 300 |
I have tried CROSS APPLY and OUTER APPLY and both give the same output.
2
Answers
Here is one way to do it without exploding each value by repeating the
CROSS APPLY
against each column. I’m sure other JSON experts can write something less verbose.Results:
This adapts easily to any number of values in the array, even non-matching. Example.
You just need a
WHERE
at the bottom of your query to match the array indexes.db<>fiddle
Admittedly this only works neatly when all the arrays are the same length.