Reputation: 4987
I have a table with an nvarchar
column that contains a serialized JSON array.
What I'm trying to do is parse that array and join the value of a property back into one string.
Here's the column content:
And in my final query, I'd like it come be displayed as one value like "Videowall" in "MergedValues". Obviously, if the array has many items, I'd like to see "Videowall, Factory, Car", etc.
Here's what I tried so far
SELECT *,
(SELECT Name
FROM OPENJSON(JsonColumn)
WITH
(
Id VARCHAR(200) '$.Id',
Name VARCHAR(200) '$.Name'
))
FROM MyTable
WHERE JsonColumn <> '[]'
This obvious error comes up
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I think it's the joining of the many parsed results that's missing.
Upvotes: 0
Views: 392
Reputation: 29943
You need to aggregate the results from the OPENJSON()
call for each row:
Table:
SELECT *
INTO Data
FROM (VALUES
(0, 0, 25200, '[{"Id":"10564", "Name": "Videowall"}]'),
(0, 0, 9200, '[{"Id":"10564", "Name": "Videowall"},{"Id":"10565", "Name": "Factory"}]')
) v (OriginalEstimateSeconds, RemainingEstimateSeconds, TimeSpentSeconds, ComponentsJSON)
Statement:
SELECT
OriginalEstimateSeconds, RemainingEstimateSeconds, TimeSpentSeconds, ComponentsJSON,
MergedValues = (
SELECT STRING_AGG([Name], ',')
FROM OPENJSON(ComponentsJSON) WITH (Name varchar(100) '$.Name')
)
FROM Data
Result:
... ComponentsJSON MergedValues
---------------------------------------------------------------------------------------------
... [{"Id":"10564", "Name": "Videowall"}] Videowall
... [{"Id":"10564", "Name": "Videowall"},{"Id":"10565", "Name": "Factory"}] Videowall,Factory
If the order of the $.Name
values in the newly generated text is important, you may use the script below:
SELECT
OriginalEstimateSeconds, RemainingEstimateSeconds, TimeSpentSeconds, ComponentsJSON,
MergedValues = (
SELECT STRING_AGG(JSON_VALUE([value], '$.Name'), ',') WITHIN GROUP (ORDER BY CONVERT(int, [key]))
FROM OPENJSON(ComponentsJSON)
)
FROM Data
Upvotes: 1
Reputation: 65218
A Subquery is not needed, but CROSS APPLY
should be used to join the table and OPENJSON
expression, and use STRING_AGG()
at the end in order to aggregate the extracted names such as
SELECT JsonColumn, STRING_AGG(Name, ',') AS [Merged Values]
FROM MyTable
CROSS APPLY OPENJSON(JsonColumn)
WITH
(
Id VARCHAR(200) '$.Id',
Name VARCHAR(200) '$.Name'
)
GROUP BY JsonColumn
Upvotes: 1