I have the following t-sql query that returns json:
SELECT
CF.Name
, UCF.Value
FROM dbo.ClaimsCustomFields CF
LEFT JOIN dbo.UserCustomFields UCF
ON UCF.FieldId = CF.Id
WHERE CF.CustomerId = 2653
FOR JSON PATH;
The output of this query is next:
[
{
"Name":"zipCode",
"Value":"zip zip zipC zipCod"
},
{
"Name":"time111zone",
"Value":"UTC +2"
},
{
"Name":"tttt",
"Value":"Company organization tessss"
}
]
But I want to get the result in the following format:
[
{
"zipCode":"zip zip zipC zipCod"
},
{
"time111zone":"UTC +2"
},
{
"tttt":"Company organization tessss"
}
]
Is it possible to achive this with FOR JSON statement?
You basically want to generate a dynamic json, so you can try to use dynamic TSQL taking advantage of SQL Server 2017 new function STRING_AGG (more info here):
--this table contains your sample data
declare #tmp table([Name] varchar(50),[Value] varchar(50))
--this variable will contain the dynamic tsql command
declare #sql nvarchar(max)
--this temp table will hold the dynamically generated json fragments
if object_id('#tmp') is null
create table #tmp (js varchar(max))
--fill table with test data
insert into #tmp values
('zipCode' ,'zip zip zipC zipCod'),
('time111zone' ,'UTC +2'),
('tttt' ,'Company organization tessss')
--generate a TSQL command that inserts each single JSON fragment into a temp table
select #sql = string_agg('insert into #tmp(js) values((select ''' + [Value] +''' as '''
+ [Name]+''' for json path , WITHOUT_ARRAY_WRAPPER))', ';')
from #tmp
--execute the dynamic TSQL command that fills the temp table with JSON fragments
exec(#sql)
--concatenate all the JSON fragments adding square brackets
select '[' + string_agg(js,',') + ']' as result from #tmp
Results:
[{"zipCode":"zip zip zipC zipCod"},{"time111zone":"UTC +2"},{"tttt":"Company organization tessss"}]
Related
In MySQL, I am trying to create a JSON_OBJECT from rows of data containing key-value pairs.
Here is the sample data:
CREATE TABLE TempValuePair( MyKey VARCHAR(64), MyValue VARCHAR(64) );
INSERT INTO TempValuePair VALUE
('Country', 'Argentina'),
('Capital', 'Buenos Aires'),
('Population', 45810000 );
The following statement seems to return an argument that conforms to the JSON_OBJECT requirements:
SELECT GROUP_CONCAT(
CONCAT( '\'', MyKey, '\',\'', Myvalue, '\'' )
ORDER BY MyKey
)
FROM TempValuePair;
However, the following statement fails:
SELECT GROUP_CONCAT(
CONCAT( '\'', MyKey, '\',\'', Myvalue, '\'' )
ORDER BY MyKey
)
FROM TempValuePair
);
Any advice about what I am doing wrong would be greatly appreciated. Thanks!
You seem to want json_objectagg, which is available in MySQL since version 5.7. The function aggregates key/value pairs from multiple rows into a single JSON object:
select json_objectagg(mykey, myvalue) as js from TempValuePair;
Yields:
{"Capital": "Buenos Aires", "Country": "Argentina", "Population": "45810000"}
Demo on DB Fiddle
This is my query:
SELECT
JSON_QUERY(MyStringColumnWithJson, '$.Images') AS images
FROM MyTable
which returns a single field with the JSON data shown here below:
"{
"Images":
[
{"Name":"test1.jpeg","Description":"originalName1.jpeg"},
{"Name":"test2.jpeg","Description":"originalName2.jpeg"},
{"Name":"test3.jpeg","Description":"originalName3.jpeg"}
]
}"
How can I read the images result row by row into a temporary table structure?
Use OPENJSON which returns a data set, not JSON_VALUE, which returns a scalar value. For example:
DECLARE #JSON nvarchar(MAX) = N'{
"Images":
[
{"Name":"test1.jpeg","Description":"originalName1.jpeg"},
{"Name":"test2.jpeg","Description":"originalName2.jpeg"},
{"Name":"test3.jpeg","Description":"originalName3.jpeg"}
]
}';
SELECT *
FROM OPENJSON(#JSON, '$.Images')
WITH (Name nvarchar(128),
Description nvarchar(128))OJ;
SELECT I.[Name],
I.Description
FROM MyTable MT
CROSS APPLY OPENJSON(MT.YourJsonColumn, '$.Images')
WITH (Name nvarchar(128),
Description nvarchar(128)) I;
I am trying to convert SQL Server results into a doubly nested JSON format.
Source SQL Server table:
ID
Name
Program
Type
Section
Director
Project
Sr Manager
PCM
Contractor
Cost Client
123
abc
qew
tyu
dd
ghghjg
hkhjk
fghfgf
gnhghj
gghgh
gghhg
456
yui
gdffgf
ghgf
jkjlkll
uiop
rtyuui
rfv
ujmk
rfvtg
efgg
Convert into doubly JSON as shown here:
[
[
{"key":"ID","value":"123"},
{"key":"Name","value":"abc"},
{"key":"Program","value":"qew"},
{"key":"Type","value":"tyu"},
{"key":"Section","value":"dd"},
{"key":"Director","value":"ghghjg"},
{"key":"Project","value":"hkhjk"},
{"key":"Sr Manager","value":"fghfgf"},
{"key":"PCM","value":"gnhghj"},
{"key":"Contractor","value":"gghgh"},
{"key":"Cost Client","value":"gghhg"}
],
[
{"key":"ID","value":"456"},
{"key":"Name","value":"yui"},
{"key":"Program","value":"gdffgf"},
{"key":"Type","value":"ghgfjhjhj"},
{"key":"Section","value":"jkjlkll"},
{"key":"Director","value":"uiop"},
{"key":"Project","value":"rtyuui"},
{"key":"Sr Manager","value":"rfv"},
{"key":"PCM","value":"ujmk"},
{"key":"Contractor","value":"rfvtg"},
{"key":"Cost Client","value":"efgg"}
]
]
Any help would be greatly appreciated.
Edit:
I started with this by rewriting the "FOR JSON AUTO" so that I can add "Key" "Value" text somehow.
But because my table has space in the column name, FOR XML PATH('') giving invalid XML identifier as required by FOR XML error.
that is when I thought of taking community help.
Create PROCEDURE [dbo].[GetSQLtoJSON] #TableName VARCHAR(255)
AS
BEGIN
IF OBJECT_ID(#TableName) IS NULL
BEGIN
SELECT Json = '';
RETURN
END;
DECLARE #SQL NVARCHAR(MAX) = N'SELECT * INTO ##T ' +
'FROM ' + #TableName;
EXECUTE SP_EXECUTESQL #SQL;
DECLARE #X NVARCHAR(MAX) = '[' + (SELECT * FROM ##T FOR XML PATH('')) + ']';
SELECT #X = REPLACE(#X, '<' + Name + '>',
CASE WHEN ROW_NUMBER() OVER(ORDER BY Column_ID) = 1 THEN '{'
ELSE '' END + Name + ':'),
#X = REPLACE(#X, '</' + Name + '>', ','),
#X = REPLACE(#X, ',{', '}, {'),
#X = REPLACE(#X, ',]', '}]')
FROM sys.columns
WHERE [Object_ID] = OBJECT_ID(#TableName)
ORDER BY Column_ID;
DROP TABLE ##T;
SELECT Json = #X;
END
Sample data:
CREATE TABLE [dbo].[Test1](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Col1] [int] NOT NULL,
[Col 2] varchar(50)
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Test1] ON
GO
INSERT [dbo].[Test1] ([ID], [Col1], [Col 2]) VALUES (1, 0,'ABCD')
GO
INSERT [dbo].[Test1] ([ID], [Col1] ,[Col 2]) VALUES (2, 1, 'POIU')
GO
SET IDENTITY_INSERT [dbo].[Test1] OFF
GO
You can use the following code:
Inside an APPLY, unpivot the columns as key/value pairs...
... and aggregate using FOR JSON PATH
Use STRING_AGG to do another aggregation.
SELECT '[' + STRING_AGG(CAST(v.json AS nvarchar(max)), ',') + ']'
FROM T
CROSS APPLY (
SELECT *
FROM (VALUES
('ID', CAST(ID AS nvarchar(100))),
('Name', Name),
('Program', Program),
('Type', [Type]),
('Section', Section),
('Director', Director),
('Project', Project),
('Sr Manager', [Sr Manager]),
('PCM', PCM),
('Contractor', Contractor),
('Cost Client', [Cost Client])
) v([key], value)
FOR JSON PATH
) v(json)
db<>fiddle
You cannot use FOR JSON again, because then you will get ["json": [{"key" : ...
first of all check this link you can find what you want
format-query-results-as-json-with-for-json-sql-server
but in your case you can try this
SELECT
ID,Name,Program,Type,Section,
Director,Project,Sr,Manager,PCM,Contractor,Cost,Client
FROM table
FOR JSON AUTO;
check the link there is more sample so it can help you
I just want to receive a json data and use it's fields as a table column for another queries.
I'm trying to make the value in the key "nameProperty" into a column in a table, and the value of the keys "newValue"fill the rows of that column.
For example:
i get a json file like this
{
"operation":{
"ID":"ABC",
"KinshipDescription":"--"
},
"fields":[
{
"property":{
"nameProperty":"ID",
"oldValue":"",
"newValue":"123456",
"confirmed":"false",
"labelProperty":"ID",
"oldValueDescription":"",
"newValueDescription":"123456"
}
},
{
"property":{
"nameProperty":"Name",
"oldValue":"",
"newValue":"John",
"confirmed":"false",
"labelProperty":"Name",
"oldValueDescription":"",
"newValueDescription":"John"
}
}
]
}
I want to extract the objects on the list "fields", but i only can make them an row for key, and another row for values like the script below makes.
DECLARE #jsonObj NVARCHAR(MAX)
--Set a result in
SET #jsonObj = (select JSON_Query(data, '$.fields') from table where id = 'ABC')
select * from openjson(#jsonObj)
with (Property nvarchar(255) '$.property.nameProperty',
newValue nvarchar(50) '$.property.newValue')
and I have no idea how I can do this
the results of this script is something like this
ID 123456
Name John
and the results that i want to see is
ID Name --column name, not a row
123456 John
The quickest (thought-wise, not necessarily performance) way I can come up with on this is using dynamic SQL. In fact, I'm pretty certain you'll have to use it.
Here's an example that can get you moving. You can run this in SSMS.
DECLARE #json NVARCHAR(MAX) =
'{
"operation":{
"ID":"ABC",
"KinshipDescription":"--"
},
"fields":[
{
"property":{
"nameProperty":"ID",
"oldValue":"",
"newValue":"123456",
"confirmed":"false",
"labelProperty":"ID",
"oldValueDescription":"",
"newValueDescription":"123456"
}
},
{
"property":{
"nameProperty":"Name",
"oldValue":"",
"newValue":"John",
"confirmed":"false",
"labelProperty":"Name",
"oldValueDescription":"",
"newValueDescription":"John"
}
}
]
}';
-- Variable to hold the column/values.
DECLARE #cols VARCHAR(MAX) = '';
-- Generate the column/value pairs.
SELECT
#cols = #cols
+ CASE WHEN ( LEN( #cols ) > 0 ) THEN ', ' ELSE '' END -- add comma if needed.
+ '''' + Properties.newValue + ''' AS [' + Properties.nameProperty + '] '
FROM OPENJSON( #json, '$.fields' ) WITH (
property NVARCHAR(MAX) '$.property' AS JSON
)
CROSS APPLY (
SELECT * FROM OPENJSON( property ) WITH (
nameProperty VARCHAR(50) '$.nameProperty',
oldValue VARCHAR(50) '$.oldValue',
newValue VARCHAR(50) '$.newValue',
confirmed VARCHAR(50) '$.confirmed',
labelProperty VARCHAR(50) '$.labelProperty',
oldValueDescription VARCHAR(50) '$.oldValueDescription',
newValueDescription VARCHAR(50) '$.newValueDescription'
)
) AS Properties;
-- Execute column/value pairs as dynamic SQL.
EXEC ( 'SELECT ' + #cols );
Which returns:
+--------+------+
| ID | Name |
+--------+------+
| 123456 | John |
+--------+------+
If you were to PRINT #cols you would see
'123456' AS [ID] , 'John' AS [Name]
A few quick notes:
Performance may vary.
Values are quoted but can be CAST if needed.
Included all 'property' fields in CROSS APPLY for example. Only specify what is needed.
Note the use of NVARCHAR when using AS JSON
May want to consider OUTER APPLY if there's potential for no 'property' present.
I received a valid JSON string from client side, it contains an array of integer values:
declare #JSON nvarchar(max) = N'{"Comments": "test", "Markets": [3, 151]}'
How to select the market IDs correctly?
If I use a query like this: select * from openjson(#JSON) j, it returns
The type of Markets is 4, which means an object,
but the query below returns null value:
select j.Markets from openjson(#JSON) with(Markets nvarchar(max)) j
My goal is to update Market table based on these IDs, eg:
update Market set Active = 1 where MarketID in (3, 151)
Is there a way to do this?
Any built-in function compatible with SQL server 2016 can be used.
Note:
Thanks to #johnlbevan
SELECT VALUE FROM OPENJSON(#JSON, '$.Markets') works perfectly for this problem.
Just for the completeness, here is how I created the JSON integer array ("Markets": [3, 151]) from SQL server.
Since there is no array_agg function out of the box in 2016, I did this:
SELECT (
JSON_QUERY('[' + STUFF(( SELECT ',' + CAST(MarketID AS VARCHAR)
FROM Market
FOR XML PATH('')),1,1,'') + ']' ) AS Markets)
To expand the Markets array alongside other columns you can do this:
SELECT Comments, Market
FROM OPENJSON('{"Comments": "test", "Markets": [3, 151]}')
WITH (Comments nvarchar(32), Markets NVARCHAR(MAX) AS JSON) AS a
CROSS APPLY OPENJSON (a.Markets) WITH (Market INT '$') AS b
Convert the string to json
Map the first field returned to the Comments column with type nvarchar(32)
Map the second field to Markets column with type nvarchar(max), then use as json to say that the contents is json (see https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql#arguments for a more detailed description - search the page for as json; the key paragraph starts at the 4th occurrence)
Use a cross apply to apply the OPENJSON function to the Markets column so we can fetch values from that property.
Finally use the WITH statement to map the name Market to the returned value, and assign it a data type of INT.
However, to just get the list of values needed to do the update, you can do this:
UPDATE Market
SET Active = 1
WHERE MarketID IN
(
SELECT value
FROM OPENJSON('{"Comments": "test", "Markets": [3, 151]}','$.Markets')
);
Again OPENJSON lets us query the string as JSON
However this time we specify a path to point at the Markets value directly (see https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql)
We now return the values returned and filter our UPDATE on those, as we would were we dealing with any other subquery.