Retrieve values in a list in JSON using TSQL - sql

I have this JSON and I want to get all the values in keyPhrases to be displayed as a column in TSQL query. Do you know how it can be done?
Desired Output:
ID
keyPhrases
778124772
banker, good position, friends family
JSON:
{"documents": [{"id": "778124772", "keyPhrases": ["banker", "good position", "friends", "family" ], "warnings": []}]}
Really appreciate your help.

The OPENJSON can help you, so the potential solution can be:
DECLARE #json NVARCHAR(MAX) = '{"documents": [{"id": "778124772", "keyPhrases": ["banker", "good position", "friends", "family" ], "warnings": []}]}';
SELECT
R.id as ID,
(SELECT STRING_AGG(value, ', ') FROM OPENJSON(R.kp)) as keyPhrases
FROM OPENJSON(#json, '$.documents')
WITH (id bigint, kp nvarchar(max) '$.keyPhrases' as JSON) R
Just to know, OPENJSON and STRING_AGG are features related to newer versions of SQL Server.

You can use OPENJSON() and STRING_AGG() as the following:
DECLARE #JSON NVARCHAR(MAX) = N'{"documents": [{"id": "778124772", "keyPhrases": ["banker", "good position", "friends", "family" ], "warnings": []}]}';
SELECT JSON_VALUE(T.Value, '$.id') AS ID,
STRING_AGG(TT.Value, ',') AS keyPhrases
FROM OPENJSON(#JSON, '$.documents') AS T
CROSS APPLY OPENJSON(Value, '$.keyPhrases') AS TT
GROUP BY JSON_VALUE(T.Value, '$.id');
Here is a db<>fiddle

Related

How to extract specific data from metadata?

I need some help on extracting some very specific data from metadata that I have from a database. Here's how part of the code and my metadata looks below. What I only need is "DESC":"Ref 188888", how may I edit the code to get what I need?
Thank you
SELECT data.metadata -> 'details' as metadata_info
FROM db_information
Results from above query:
{"DATE":null,"CD":"25","TAMT":80.00,"CHENBR":null,"DESC":"Ref 188888","DESS":" APS",........ many other unnecessary stuff}
Refer to the below script.
DECLARE #json NVarChar(2048) = N'{
"DATE": null,
"CD": "25",
"TAMT": 80.00,
"CHENBR": null,
"DESC": "Ref 188888",
"DESS": " APS"
}';
SELECT *
FROM OpenJson(#json);
SELECT JSON_VALUE(#json, '$.DESC') AS [DESC];

Add data type to JSON values query

I am building the following view on SQL Server. The data is extracted from Soap API via Data Factory and stored in SQL table. I union two pieces of the same code because I am getting outputs from API as a Objects or Arrays.
This query works, however when try to order or filter the view got this error:
JSON text is not properly formatted. Unexpected character '.' is found at position 12.
/*Object - invoiceDetails*/
SELECT
XML.[CustomerID],
XML.[SiteId],
XML.[Date],
JSON_VALUE(m.[value], '$.accountNbr') AS [AccountNumber],
JSON_VALUE(m.[value], '$.actualUsage') AS [ActualUsage]
FROM stage.Bill XML
CROSS APPLY openjson(XML.xmldata) AS n
CROSS APPLY openjson(n.value, '$.invoiceDetails') AS m
WHERE XML.XmlData IS NOT NULL
AND ISJSON (XML.xmldata) > 0
AND n.type = 5
AND m.type = 5
UNION ALL
/*Array - invoiceDetails*/
SELECT
XML.[CustomerID],
XML.[SiteId],
XML.[Date],
JSON_VALUE(o.[value], '$.accountNbr') AS [AccountNumber],
JSON_VALUE(o.[value], '$.actualUsage') AS [ActualUsage]
FROM stage.Bill XML
CROSS APPLY openjson(XML.xmldata) AS n
CROSS APPLY openjson(n.value) AS m
CROSS APPLY openjson(m.value, '$.invoiceDetails') AS o
WHERE XML.XmlData IS NOT NULL
AND ISJSON (XML.xmldata) > 0
AND n.type = 4
Just did a small exercise using the WITH clause in order to specify data types to the values and noticed I am able to order and filter the view. So I believe the way is to add data type to this query. My problem now is that I don't know how to add WITH clause to my query in order to make it work.
Any advice?
My apologies, you might find the XML naming and prefixes confusing. In my first tests, I supposed to received XML data from Data Factory so my table and columns includes XML prefixes untill I noticed Data Factory delivers JSON data, so started query data as JSON but I have not changed table name and prefixes.
Thank you for your comments to enrich this question. I took this example below from a YouTube channel (Not sure if I am allowed to mention channel's name:https://www.youtube.com/watch?v=yl9jKGgASTY&t=474s). I believe it is a similar approach. Could you please help how could I add the WITH clause in order to specify data types?
DECLARE #json NVARCHAR(MAX)
SET #json =
N'{
"OrderHeader": [
{
"OrderID": 100,
"CustomerID": 2000,
"OrderDetail": [
{
"ProductID": 2000,
"UnitPrice": 350
},
{
"ProductID": 5000,
"UnitPrice": 800
},
{
"ProductID": 9000,
"UnitPrice": 200
}
]
}
]
}'
SELECT
JSON_VALUE(a.value, '$.OrderID') AS OrderID,
JSON_VALUE(a.value, '$.CustomerID') AS CustomerID,
JSON_VALUE(a.value, '$.ProductID') AS ProductID,
JSON_VALUE(a.value, '$.UnitPrice') AS UnitPrice
FROM OPENJSON(#json, '$.OrderHeader') AS a
CROSS APPLY OPENJSON(a.value, 'OrderDetail') AS b
You have a couple of typos.
The second OPENJSON should have the path starting $.
The third and fourth SELECT columns should use b.value not a.value
DECLARE #json NVARCHAR(MAX)
SET #json =
N'{
"OrderHeader": [
{
"OrderID": 100,
"CustomerID": 2000,
"OrderDetail": [
{
"ProductID": 2000,
"UnitPrice": 350
},
{
"ProductID": 5000,
"UnitPrice": 800
},
{
"ProductID": 9000,
"UnitPrice": 200
}
]
}
]
}'
SELECT
JSON_VALUE(a.value, '$.OrderID') AS OrderID,
JSON_VALUE(a.value, '$.CustomerID') AS CustomerID,
JSON_VALUE(b.value, '$.ProductID') AS ProductID,
JSON_VALUE(b.value, '$.UnitPrice') AS UnitPrice
FROM OPENJSON(#json, '$.OrderHeader') AS a
CROSS APPLY OPENJSON(a.value, '$.OrderDetail') AS b;
An alternative syntax is to use OPENJSON on each object with an explicit schema
SELECT
oh.OrderID,
oh.CustomerID,
od.ProductID,
od.UnitPrice
FROM OPENJSON(#json, '$.OrderHeader')
WITH (
OrderID int,
CustomerID int,
OrderDetail nvarchar(max) AS JSON
) AS oh
CROSS APPLY OPENJSON(oh.OrderDetail)
WITH (
ProductID int,
UnitPrice decimal(18,9)
) AS od;
db<>fiddle

Create JSON string using variable

I am trying to get following JSON string:
[{
"Name": "John",
"AccountType": 1
},
{
"Name": "Steven",
"AccountType": 1
}
]
I know that AccountType will be always 1 and I have string variable in following format "John;Steven;Brian;Mike"
I was trying to build this JSON using XML PATH and splitToTable function but with no success. How can I achieve it?
Thanks in advance.
In SQL Server 2016 Microsoft added some useful JSON functions. So this can be achieved very easily:
DECLARE #Variable nvarchar(max) = 'John;Steven;Brian;Mike';
SELECT [value] as Name, 1 as AccountType FROM STRING_SPLIT(#Variable,';')
FOR JSON PATH
More info about this functions here - https://learn.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver15
You can use string_split() and for json:
declare #str nvarchar(max) = 'John;Steven;Brian;Mike';
select *
from (
select value as [Name], 1 as [AccountType]
from string_split(#str, ',')
) t
for json auto;

Dealing with nested JSON in SQL OPENJSON WITH command?

I have JSON value that has some structure to it but I'm struggling to get to the 3rd level. I am using CROSS APPLY OPENJSON to get to the "Lines" data but I need to get the "Code" out of the TaxCode area... It seems to be it's own JSON array maybe?
Any help would be appreciated... This is what I have so far...
DECLARE #JSONText NVarChar(max) = '{
"UID": "845bc256-6027-4a89-8c05-35e4bb8e6aba",
"Number": "00013608",
"Lines": [{
"RowID": 1,
"Total": 20.0,
"TaxCode": "#{UID=f2cc83e5-0f7f-4831-9d88-dbe110e0683a; Code=S15}"
},{
"RowID": 2,
"Total": 55.49,
"TaxCode": "#{UID=a5cc34e5-0fr4-4325-9d67-bdh110e0683a; Code=S17}"
}]
}';
SELECT J.[UID],J.[Number],LI.*
FROM OPENJSON (#JSONText)
WITH (
[UID] nvarchar(512) '$."UID"',
[Number] nvarchar(50) '$."Number"',
[LineItems] NVarChar(max) '$."Lines"' AS JSON
) J
CROSS APPLY OPENJSON (J.[LineItems])
WITH (
[RowID] INT '$."RowID"',
[Total] Decimal(12,2) '$."Total"',
[TaxCode] NVarChar(512) '$."TaxCode"',
[TaxCodeTest] NVarChar(50) '$."TaxCode.Code"'
) LI;
As the TaxCode value being supplied wasn't a "true" JSON object I had to use some SQL to work with it as a string end get the required data. I ended up creating a function to do it using inspiration from this question...
A SQL Query to select a string between two known strings

DB2 LUW - JSON_Table reading json array data into tabular format

I am trying to convert JSON array data into tabular format using Json_Table function. I tried to run the below query but I am getting the following errors:
SQL‬‎/‪JSON‬‎ ‪scalar‬‎ ‪required‬‎.‪‬‎.‪‬‎ ‪SQLCODE‬‎=‪‬‎-‪16413‬‎,‪‬‎ ‪SQLSTATE‬‎=‪2203F‬‎,‪‬‎ ‪DRIVER‬‎=‪4‬‎.‪19‬‎.‪56).
The same query is working fine when the number of elements in Employees array is 1, but not otherwise.
SELECT E."id", E."name"
FROM JSON_TABLE
(
'{
"Employees": [
{
"id": 1,
"name": "Kathi"
},
{
"id": 2,
"name": "Pavan"
}
]
}', 'strict $' COLUMNS
(
"id" INTEGER PATH 'strict $.Employees[*].id'
, "name" VARCHAR(20) PATH 'strict $.Employees[*].name'
) ERROR ON ERROR
) AS E;
Just for the benefit of others who are looking for some examples, i found below link in internet, example 3 basically helps with my case. We need to use JSON_Table from SysTools schema.
https://www.worldofdb2.com/profiles/blogs/convert-json-data-to-relational-format
JSON_TABLE produces 1 row only per 1 json document.
You may use the following only:
"id" INTEGER PATH 'strict $.Employees[n].id'
, "name" VARCHAR(20) PATH 'strict $.Employees[n].name'
where n={0, 1} for an array of 2 elements as in your example.