Reputation: 637
I would like to format a json string '[{"_":7},{"_":13},{"_":17}]'
as '[7,13,17]'
Tried with REPLACE Method in TSQL. I have to use REPLACE method three times to get the desire result.
SELECT REPLACE(REPLACE(REPLACE('[{"_":7},{"_":13},{"_":17}]','},{"_":',', '),'{"_":',''),'}','')
is there a better way to do that? I am using SQL Server 2016.
After some comments for this post, This my actual issue.
I have some customer data. Customer Table
CustomerId | Name
1 ABC
2 XYZ
3 EFG
each customer has some area of interest. Customer Area of Interest
CustomerAreaInterestId | FK_CustomerId | FK_AreaOfInterestId
1 1 2
2 1 3
3 1 5
4 2 1
5 2 2
6 3 3
7 3 4
Area of interest table
AreaOfInterestId | Description
1 Interest1
2 Interest2
3 Interest3
4 Interest4
5 Interest5
In the final result set, I have to include area of interest id's as an array of value
[
{
"CustomerName": "ABC",
"AreaofInterest": "[2,3,5]"
},
{
"CustomerName": "XYZ",
"AreaofInterest": "[1,2]"
},
{
"CustomerName": "EFG",
"AreaofInterest": "[3,4]"
}
]
The result consists with some other data’s as well. I have omitted for the code brevity.
Upvotes: 0
Views: 2080
Reputation: 131553
Short Version
Cast the numeric field to text before trying to aggregate it
From the comments, it looks like the real question is how to use JSON to aggregate strings in SQL Server 2016, as shown in this answer.
SELECT
JSON_VALUE(
REPLACE(
(SELECT _ = someField FROM someTable FOR JSON PATH)
,'"},{"_":"',', '),'$[0]._'
)
or, rewritten for clarity :
SELECT
JSON_VALUE( REPLACE(
(SELECT _ = someField
FROM someTable
FOR JSON PATH)
,'"},{"_":"',', ')
,'$[0]._')
That query works only with string fields. One needs to understand what it does before it can be adopted to other types.
'[{"_":"value1"},{"_":"value2"}]'
.REPLACE
replaces the quotes and separators between objects, changing that array of objects to '[{"_":"value1,value2"}]'
. That's a single object in an array, whose single attribute is a comma-separated string.JSON_VALUE(...,,'$[0]._')
extracts the _
attribute of that single array item.That trick can't be used with numeric values because they don't have quotes. The solution is to cast them to text first:
SELECT
JSON_VALUE( REPLACE(
(SELECT _ = CAST(someNumber as nvarchar(20))
FROM someTable
FOR JSON PATH)
,'"},{"_":"',', ')
,'$[0]._')
Eg :
declare @t table (id int)
insert into @t
values
(7),
(13),
(17)
SELECT
JSON_VALUE( REPLACE(
(SELECT _ = cast(ID as nvarchar(20))
FROM @t
FOR JSON PATH)
,'"},{"_":"',', '),'$[0]._')
The only change from the original query is the cast
clause.
This produces :
7, 13, 17
This conversion is localized so care must be taken with decimals and dates, to avoid producing unexpected results, eg 38,5, 40,1
instead of 38.5, 40.1
.
PS: That's no different than the XML technique, except STUFF
is used there to cut off the leading separator. That technique also needs casting numbers to text, eg :
SELECT STUFF(
( SELECT N', ' + cast(ID as nvarchar(20))
FROM @t FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),
1,2,N'')
Upvotes: 2
Reputation: 29983
If you want to use only JSON
functions (not string-based approach), the next example may help:
DECLARE @json nvarchar(max) = N'[{"_":7},{"_":13},{"_":17}]'
DECLARE @output nvarchar(max) = N'[]'
SELECT @output = JSON_MODIFY(@output, 'append $', j.item)
FROM OPENJSON(@json) WITH (item int '$."_"') j
SELECT @output AS [Result]
Result:
Result
[7,13,17]
Of course, the approach based on string aggregation is also a possible solution:
DECLARE @json nvarchar(max) = N'[{"_":7},{"_":13},{"_":17}]'
SELECT CONCAT(
N'[',
STUFF(
(
SELECT CONCAT(N',', j.item)
FROM OPENJSON(@json) WITH (item int '$."_"') j
FOR XML PATH('')
), 1, 1, N''
),
N']'
)
Upvotes: 2