Select specific value from JSON list with SQL - sql

Suppose I have a table column with person data organized as a JSON array, with categories and names.
In SQL, I can then easily select the data for a specific element in the array:
SELECT JSON_VALUE('{ "Persons": [{"PersonCat":"1","Name":"John"},{"PersonCat":"2","Name":"Henry"}]}','$.Persons[0].Name') AS SelectedPerson
I will then get "John".
But what if I want the person with "PersonCat" = 2? And null if PersonCat does not exist in the list?

I'm not sure it is possible to do this with the JSON_VALUE method, but it is possible using OPENJSON
DECLARE #json nvarchar(max)
SET #json = '{ "Persons": [{"PersonCat":"1","Name":"John"},{"PersonCat":"2","Name":"Henry"},{"Name":"Bob"}]}'
SELECT[PersonCat], [Name]
FROM OPENJSON(#json, '$.Persons')
WITH (
PersonCat NVARCHAR(512) '$.PersonCat',
[Name] NVARCHAR(512) '$.Name'
)
You can then add a WHERE clause to the SELECT to find the relevant PersonCat value (note: where the PersonCat property is missing from the array entry, the PersonCat column will be NULL)

Related

How to get data from json column in SQL Server that starts with array element

I have a database table that I need to extract data from where the column of interest has json it. What makes this particularly difficult is the most outer elements of the json is '[' & ']' as in the parent element is an array. I need to get the value associated with key 'Name' (which in this case is 'MS220'). However, I'm not able to path correctly to the key I want.
The below JData table is a duplicate copy of the data I need to perform the extract on. Between SELECT OPENJSON, JSON_VALUE, JSON_QUERY etc., how can I retrieve the value I'm looking for?
Below is a couple of selects I've tried but not quite getting it.
CREATE TABLE JData
(
JsonData nvarchar(max)
)
INSERT INTO JData (JsonData)
VALUES
('[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "MS220"
}
]')
SELECT *
FROM OPENJSON (JData,'$.[0]')
WITH (
[Name] varchar(10) '$.Name'
)
SELECT
JSON_VALUE(JData,'$') as v
#AaronBertrand: I had to modify the answer a little since the table also has a column labeled [name] as well. Is there a way to UPDATE ParamName to a new value?
SELECT
t.[Name],
ParamName
FROM
[myDB].[dbo].[myTable] t
CROSS APPLY
OPENJSON (t.params)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
ParamName varchar(10) '$.Name'
);
SELECT Name FROM dbo.JData
CROSS APPLY OPENJSON (JsonData)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
[Name] varchar(10)
);
Example db<>fiddle

Parse JSON in SQL

I'm looking to parse a single return in JSON into multiple rows.
The string is this -
{"policy_ids":["INZP2981-11000002","INZP-00001786","0AAAA01PC06"]}
I want to just parse this so that it is a row for each policy_ids. I've tried using OpenJSON WITH however I keep returning NULL values.
DECLARE #json NVARCHAR(MAX) ;
SET #json = N'{"policy_ids":["INZP2981-11000002","INZP-00001786","0AAAA01PC06"]}' ;
SELECT
*
FROM
OPENJSON(#json)
WITH (
policy_ids varchar(200) '$.policy_ids'
)
Help is appreciated.
You need a different statement to parse the $.policy_ids JSON array. You may try tou use OPENJSON() with default schema (without the WITH clause). In this case the result is a table with columns key, value and type and the value column returns the value of each item in the input array.
DECLARE #json NVARCHAR(MAX) ;
SET #json = N'{"policy_ids":["INZP2981-11000002","INZP-00001786","0AAAA01PC06"]}' ;
SELECT [value] AS policy_id
FROM OPENJSON(#json, '$.policy_ids')
Result:
policy_id
-----------------
INZP2981-11000002
INZP-00001786
0AAAA01PC06
If you want to use an explicit schema, the statement is:
SELECT *
FROM OPENJSON(#json, '$.policy_ids') WITH (
policy_id varchar(200) '$'
)

SQL - openjson to extract key from json

Below #json contains 3 data object within an array. After using OPENJSON to extract these objects to a Table variable, please see the output attached.
DECLARE #json NVARCHAR(MAX);
SET #json = N'[{"Container":"MSKU2913236","Seal":"ML-TH4773979","Size":"20","Temperature":"-20","TareWeight":"3.132","CreatedDate":"02-02-2018 00:00:00","Comment":null,"NetWeight":"21.445","TempRec#":null},{"Container":"MSKU3432702","Seal":"ML-TH4773972","Size":"20","Temperature":"-40","TareWeight":"2.872","CreatedDate":"02-02-2018 00:00:00","Comment":null,"NetWeight":"23.932","TempRec#":"TR12345"},{"Container":"MSKU4043053","Seal":"ML-TH4773973","Size":"20","Temperature":"-20","TareWeight":"2.995","CreatedDate":"02-02-2018 00:00:00","Comment":null,"NetWeight":"22.4","TempRec#":null}]';
DECLARE #ContainerTable TABLE(
[Key] NVARCHAR(100),
[Data] NVARCHAR(MAX)
);
INSERT INTO #ContainerTable
SELECT [key], [value] FROM OPENJSON(#json)
SELECT * FROM #ContainerTable
Output
Objective is to replace the Key column values with the Container property value from json in the Data column for all 3 rows.
Expected Output
Note: Expected output is hard coded and it only shows the one row but same is required for all rows.
You could use JSON_VALUE:
INSERT INTO #ContainerTable([Key], [Data])
SELECT JSON_VALUE([value],'$.Container'), [value]
FROM OPENJSON(#json);
DBFiddle Demo

SQL 2017 : Need to convert json with column name as a value and actual value is value of another one

HI I need to convert Json stored in 1 of the columns in a table to flat tables with specific fields.
Note : Column names are not always ""Request type,Country...".Columsn are dynamic and should be picked from value in "Name"
Below is the json from 1 row.
{"JobID":1,"ItemID":1,"Attributes":[{"ID":1,"Name":"Request Type","Value":"1","ValueString":"Buy"},{"ID":3,"Name":"Country","Value":"2","ValueString":"USA"},{"ID":5,"Name":"Number","Value":"1","ValueString":"1"}]}
I need this to be converted as in attached format
As a starter you should check OPENJSON:
DECLARE #j NVARCHAR(MAX) = '{"JobID":1,"ItemID":1,"Attributes":[{"ID":1,"Name":"Request Type","Value":"1","ValueString":"Buy"},{"ID":3,"Name":"Country","Value":"2","ValueString":"USA"},{"ID":5,"Name":"Number","Value":"1","ValueString":"1"}]}'
And query:
SELECT *
FROM OPENJSON(#j)
WITH (JobID INT '$.JobID',
ItemId INT '$.ItemID',
[Request_Type] NVARCHAR(100) '$.Attributes[0].ValueString',
Country NVARCHAR(100) '$.Attributes[1].ValueString',
[Number] NVARCHAR(100) '$.Attributes[2].ValueString'
);
DBFiddle Demo

Store selected column names in user-defined table

I'm currently facing a problem with searching values from columns specified in user-defined table. I've got my .NET program in which I define which parameters are going to be searched for. I've decided that the best way to achieve this is to store this values (selected columns) in a list. Now I have to do something like that:
SELECT
#MyColumnNamesInAList <- I do not know how to iterate it properly
FROM
xyz
What is more, I have to insert NULL if there is no corresponding column in xyz.
In C# code I would do something like this:
foreach(var column in MyColumnNamesInAList)
{
if(!xyz.Contains(column)
"NULL AS " + column.Name;
}
#MyColumnNamesInAList <- I do not know how to iterate it properly
DECLARE #MyColumnNamesInAList VARCHAR(50) = 'ID,Name'
DECLARE #xml AS XML
SET #xml = CAST(('<X>'+REPLACE(#MyColumnNamesInAList,',' ,'</X><X>')+'</X>') AS XML)
SELECT N.value('.', 'varchar(10)') AS Columns FROM #xml.nodes('X') AS T(N)
/*
Columns
--------
ID
Name
*/
In C# code I would do something like this:
foreach(var column in MyColumnNamesInAList)
{
if(!xyz.Contains(column)
"NULL AS " + column.Name;
}
Consider we have a table as
CREATE TABLE [dbo].[tblTesttable]([ID] [int] IDENTITY(1,1) NOT NULL,[Name] [varchar](50) NULL)
Now If we execute the below query, we can figure out the extra columns -
DECLARE #MyColumnNamesInAList VARCHAR(50) = 'ID,Name,NewColumn1,NewColumn2'
DECLARE #xml AS XML
SET #xml = CAST(('<X>'+REPLACE(#MyColumnNamesInAList,',' ,'</X><X>')+'</X>') AS XML)
SELECT X.Column_Name
FROM (SELECT N.value('.', 'varchar(10)') AS Column_Name FROM #xml.nodes('X') AS T(N))X
EXCEPT
(SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'tblTesttable')
/*
Column_Name
-----------
NewColumn1
NewColumn2
*/
What is more, I have to insert NULL if there is no corresponding
column in xyz.
Now here I will give you a hint (I want you to solve this part) (:
You need to issue
ALTER TABLE N'tblTesttable' ADD NewColumn1 VARCHAR(20) NULL
ALTER TABLE N'tblTesttable' ADD NewColumn2 VARCHAR(20) NULL
You need to build the query dynamically and using the previous stuffs that we shared.
Hope you understand.
All the best!!!
You should dynamically generate the query directly in your .NET program.
You could do it with system view and the EXEC command but that will run poorly on SQL Server.
Watch out for SQL injection if the values you're using come from the end-user.