SQL OPENJSON get only first element - sql

I'm trying to get data from only the first element in the JSON string because the first element will always be the newest. I have tried a few things with no luck. Maybe someone here can point me in the right direction.
This is the JSON string:
[
{
"wd:Transaction_Log_Entry": [
{
"wd:Transaction_Log_Reference": {
"#wd:Descriptor": "Rescind of End Contract: XXXX (Rescinded)",
"wd:ID": {
"#wd:type": "WID",
"#text": "fb27bafef89b101b5bf865947b420000"
}
},
"wd:Transaction_Log_Data": {
"wd:Transaction_Log_Description": "Rescind of End Contract: XXXX (Rescinded)",
"wd:Transaction_Effective_Moment": "2023-01-18T09:00:00+01:00",
"wd:Transaction_Entry_Moment": "2023-01-19T10:49:00.868+01:00",
"wd:Is_Rescind_Or_Rescinded": "1",
"wd:Is_Correction_Or_Corrected": "0"
}
},
{
"wd:Transaction_Log_Reference": {
"#wd:Descriptor": "End Contract: XXXX (Rescinded)",
"wd:ID": {
"#wd:type": "WID",
"#text": "a4a0fd2c2df8101bd1c6bde5f5710000"
}
},
"wd:Transaction_Log_Data": {
"wd:Transaction_Log_Description": "End Contract: XXXX (Rescinded)",
"wd:Transaction_Effective_Moment": "2023-01-18T09:00:00+01:00",
"wd:Transaction_Entry_Moment": "2023-01-18T12:41:43.867+01:00",
"wd:Is_Rescind_Or_Rescinded": "1",
"wd:Is_Correction_Or_Corrected": "0"
}
}
]
}
]
And my SQL query - I'm selecting the JSON string from a table that has the column name 'Transaction_Log_Entry_Data'
SELECT Effective_Moment, Entry_Moment
FROM [dbo].[Daily_And_Future_Terminations_Transaction_Log_Source]
CROSS APPLY OPENJSON (Transaction_Log_Entry_Data, '$[0]."wd:Transaction_Log_Entry"')
WITH (
Effective_Moment NVARCHAR(50) '$."wd:Transaction_Log_Data"."wd:Transaction_Effective_Moment"',
Entry_Moment NVARCHAR(50) '$."wd:Transaction_Log_Data"."wd:Transaction_Entry_Moment"'
)
And my results is 2 rows and I only want data from the first element:
Best regards
Ole

You have an arry in an array, so you must write.
JSOn is an interesting data structure, but you need a lot of experience with it
SELECT Effective_Moment, Entry_Moment
FROM [Daily_And_Future_Terminations_Transaction_Log_Source]
CROSS APPLY OPENJSON (Transaction_Log_Entry_Data, '$[0]."wd:Transaction_Log_Entry"[0]')
WITH (
Effective_Moment NVARCHAR(50) '$."wd:Transaction_Log_Data"."wd:Transaction_Effective_Moment"',
Entry_Moment NVARCHAR(50) '$."wd:Transaction_Log_Data"."wd:Transaction_Entry_Moment"'
)
Effective_Moment
Entry_Moment
2023-01-18T09:00:00+01:00
2023-01-19T10:49:00.868+01:00
fiddle
SELECT TOP 1 Effective_Moment, Entry_Moment
FROM [Daily_And_Future_Terminations_Transaction_Log_Source]
CROSS APPLY OPENJSON (Transaction_Log_Entry_Data, '$[0]."wd:Transaction_Log_Entry"')
WITH (
Effective_Moment NVARCHAR(50) '$."wd:Transaction_Log_Data"."wd:Transaction_Effective_Moment"',
Entry_Moment NVARCHAR(50) '$."wd:Transaction_Log_Data"."wd:Transaction_Entry_Moment"'
)
ORDEr By Entry_Moment DESC
Effective_Moment
Entry_Moment
2023-01-18T09:00:00+01:00
2023-01-19T10:49:00.868+01:00
fiddle

Related

SQL Query to get the json array values by comma separated

I have the below Json object. I need to get the task names by comma (,) separated.
{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC",
"Task" : [
{
TaskID : 1222,
Name: "TaskA"
},
{
TaskID : 154,
Name: "TaskB"
}
]
},
{
"ID": 11,
"Name": "ABCD",
"Task" : [
{
TaskID : 222,
Name: "TaskX"
},
{
TaskID : 234,
Name: "TaskY"
}
]
},
]
}]}
The expected Output should be in the below table. I need the task names should be comma separated.
ModelName ObjectID ObjectName TaskName
Test Model 1 ABC TaskA, TaskB
Test Model 11 ABCD TaskX, TaskY
I tried the below query. But I don't know how to group Task names.
SELECT S1.ModelName,
S2.ID AS ObjectID,
S2.Name AS ObjectName,
S3.TaskName
FROM TableA
CROSS APPLY OPENJSON(JsonData)
WITH (Model NVARCHAR(MAX) '$.Model[0]' AS JSON) S1
CROSS APPLY OPENJSON (S1.Model)
WITH (Object NVARCHAR(MAX) '$.Object' AS JSON,
ID INT '$.ID',
Name NVARCHAR(250) '$.Name') S2
CROSS APPLY OPENJSON (S2.Object)
WITH (Task NVARCHAR(MAX) '$.Task' AS JSON ,
TaskName NVARCHAR(MAX) '$.TaskName') S3
Corrected the json to a valid format and here is the SQL query for your desired output. The below query compiles and runs well in Oracle Compiler
SELECT * FROM JSON_TABLE(
'{"Model":[{"ModelName":"Test Model","Object":[{"ID":1,"Name":"ABC","Task":[{"TaskID":1222,"Name":"TaskA"},{"TaskID":154,"Name":"TaskB"}]},{"ID":11,"Name":"ABCD","Task":[{"TaskID":222,"Name":"TaskX"},{"TaskID":234,"Name":"TaskY"}]}]}]}',
'$.Model[*]'
COLUMNS (
-- L_MODEL_ROWNUM FOR ORDINALITY,
L_MODEL_NAME VARCHAR2(10) PATH '$.ModelName',
NESTED PATH '$.Object[*]' COLUMNS (
--L_OBJECT_ROWNUM FOR ORDINALITY,
L_OBJECT_ID NUMBER PATH '$.ID',
L_OBJECT_NAME VARCHAR2(10) PATH '$.Name',
L_TASK_NAME VARCHAR2(100) FORMAT JSON WITH WRAPPER PATH '$.Task[*].Name'
)
)
)
Here is the query which runs on SQL Server 2019,
DECLARE #JSONDATA NVARCHAR(MAX);
SET
#JSONDATA = N'{"Model":[{"ModelName":"Test Model","Object":[{"ID":1,"Name":"ABC","Task":[{"TaskID":1222,"Name":"TaskA"},{"TaskID":154,"Name":"TaskB"}]},{"ID":11,"Name":"ABCD","Task":[{"TaskID":222,"Name":"TaskX"},{"TaskID":234,"Name":"TaskY"}]}]}]}';
WITH TASK AS
(
SELECT
MODEL,
ID,
NAME,
TASK_NAME
FROM
OPENJSON(#JSONDATA) WITH (MODELS NVARCHAR(MAX) '$.Model' AS JSON) CROSS APPLY OPENJSON(MODELS) WITH (MODEL NVARCHAR(80) '$.ModelName', OBJECTS NVARCHAR(MAX) '$.Object' AS JSON) CROSS APPLY OPENJSON(OBJECTS ) WITH (ID INT '$.ID', NAME NVARCHAR(250) '$.Name', TASKS NVARCHAR(MAX) '$.Task' AS JSON ) CROSS APPLY OPENJSON (TASKS) WITH (TASK_NAME NVARCHAR(80) '$.Name')
)
SELECT DISTINCT
MODEL AS MODELNAME,
ID AS OBJECTID,
NAME AS OBJECTNAME,
STUFF((
SELECT
',' + [TASK_NAME]
FROM
TASK T1
WHERE
T1.[ID] = T2.[ID] FOR XML PATH('')), 1, 1, '') AS TASKNAME
FROM
TASK T2;

MSSQL Query JSON displays Null value

I have a table PublicRelations with a column called Students in a SQL Server database called Subjects.
[
{ "Label": "Name", "ColumnValue": "Trudie" },
{ "Label": "Class", "ColumnValue": "PublicRelations" },
{ "Label": "Room", "ColumnValue": "8049" },
{ "Label": "HttpPath", "ColumnValue": "https://www.google.com/" }
]
I only get NULL when I run the below query using the Json_value. I'd like to get it to display the value from the array. I believe this may have to do with the 4000 character limit?
SELECT [StuduentID],
[Students],
--JSON_VALUE([Students],'$.ColumnValue') AS Name --Only returns NULL
FROM [Subjects].[dbo].[PublicRelations] c
CROSS APPLY OPENJSON(c.Students)
WITH ( Name int '$.Name',
Value nvarchar(255) '$.ColmunValue'
) AS jsonValues
WHERE jsonValues.ColumnValue = 'Trudie'
The query works and I can find what I need, but again, I only get NULL when I want to display that part of the JSON column in my results.
The statement is wrong and you has the following issues (as #MartinSmith already mentioned):
Syntax error - '$.ColmunValue' should be '$.ColumnValue'.
Wrong schema definition (the WITH clause) - I can't see Name key in the input JSON.
Wrong use of JSON_VALUE() - this function extracts scalar value from a JSON string, so JSON_VALUE([Students],'$.ColumnValue') returns NULL with this JSON input in lax mode.
You may try with the following statement (based on the statement in the question):
Table:
CREATE TABLE PublicRelations (
StudentID int,
Students nvarchar(1000))
INSERT INTO PublicRelations (StudentID, Students)
VALUES (1, N'[
{ "Label": "Name", "ColumnValue": "Trudie" },
{ "Label": "Class", "ColumnValue": "PublicRelations" },
{ "Label": "Room", "ColumnValue": "8049" },
{ "Label": "HttpPath", "ColumnValue": "https://www.google.com/" }
]')
Statement:
SELECT p.StudentID, j.*
FROM [PublicRelations] p
CROSS APPLY OPENJSON(p.Students) WITH (
Name nvarchar(50) '$.Label',
Value nvarchar(255) '$.ColumnValue'
) j
WHERE EXISTS (
SELECT 1
FROM OPENJSON(p.Students) WITH (Value nvarchar(255) '$.ColumnValue')
WHERE Value = N'Trudie'
) AND (j.Name IN ('Name', 'Class', 'Room'))
Result:
StudentID Name Value
1 Name Trudie
1 Class PublicRelations
1 Room 8049

How to write a select query to get the index value from Json object

I have the below JSON object. I need to write a select query to get the index values of Object JSON array. Kind of getting the sequence value.
{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC",
},
{
"ID": 11,
"Name": "ABCD",
},
{
"ID": 15,
"Name": "ABCDE",
},
]
}]}
Expected Output:
Index_Value
1
2
3
If I understand the question correctly and you want to get the index of the items in the Object JSON array, you need to use OPENJSON() with default schema. The result is a table with columns key, value and type and in case of JSON array, the key column holds the index of each item in the array (0-based):
JSON:
DECLARE #json nvarchar(max) = N'{
"Model":[
{
"ModelName":"Test Model",
"Object":[
{
"ID":1,
"Name":"ABC"
},
{
"ID":11,
"Name":"ABCD"
},
{
"ID":15,
"Name":"ABCDE"
}
]
}
]
}'
Statement:
SELECT CONVERT(int, j2.[key]) + 1 AS item_id
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value], '$.Object') j2
But if you want to get the values of the ID keys in the Object JSON array, the statement is different:
SELECT j2.ID
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value], '$.Object') WITH (
ID int '$.ID'
) j2
Note, that you need two OPENJSON() calls, because the input JSON has nested array structure. Of course, if Model JSON array has always one item, you may simplify the statement using an appropriate path:
SELECT CONVERT(int, [key]) + 1 AS item_id
FROM OPENJSON (#json, '$.Model[0].Object')
Finally, to get index, ID and Name, you should use the following statement, which assumes, that $.Model JSON array has more than one item and defines ID and Name columns with the appropraite data types:
SELECT
CONVERT(int, j2.[key]) + 1 AS ItemID,
j3.ID, j3.Name
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value], '$.Object') j2
CROSS APPLY OPENJSON(j2.[value], '$') WITH (
ID int '$.ID',
Name varchar(50) '$.Name'
) j3
DECLARE #json nvarchar(max) = N'{
"Model":[
{
"ModelName":"Test Model",
"Object":[
{
"ID":1,
"Name":"ABC"
},
{
"ID":11,
"Name":"ABCD"
},
{
"ID":15,
"Name":"ABCDE"
}
]
}
]
}'
declare #i int=0;
SELECT
j2.ID, j2.Name
FROM OPENJSON (#json, '$.Model') j1
CROSS APPLY OPENJSON(j1.[value],concat('$.Object[',#i,']')) WITH (
ID i`enter code here`nt '$.ID', Name varchar(100) '$.Name'
) j2
Results:-
ID
Name
11
ABCD
you can select the key columns in select clause no need to mention in with of crossjoin.
SELECT
distinct t.id,
JSON_VALUE(AttsData.[value], '$.address') as address,
JSON_VALUE(AttsData.[value], '$.name') as name,
JSON_VALUE(AttsData.[value], '$.owner_name') as owner_name,
JSON_VALUE(AttsData.[value], '$.project') as project
,CONVERT(int, AttsData.[key]) index_id
FROM mytablewithjsonfeild t
CROSS APPLY OPENJSON (t."jsonfeild",N'$.parentkey') as AttsData
Above query, from the table I have cross joined the JSON field. and in select statement i have taken the specific keys.
and CONVERT(int, AttsData.[key]) to get the index of the elements

SQL Query on Json object inside multiple JSON objects

I have the below Json string. I need to write a query to get the TP records. Without providing the index value, we need get the result.
{
"S": [
{
"Name": "Project1",
"SP": [
{
"ID": 1,
"Name": "Test1",
"TP": [
{
"TID": 11,
"TName": "TT1",
},
{
"TID": 12,
"TName": "TT2",
},
]
},
{
"ID": 2,
"Name": "Test2",
"TP": [
{
"TID": 13,
"TName": "TT3",
},
{
"TID": 14,
"TName": "TT4",
},
]
},
]}]}
How do I query to get the TP values.
Expected Result:
TID TName
11 TT1
12 TT2
13 TT3
14 TT4
You can use OPENJSON function containing WITH Clause added as many CROSS APPLY Clause as upto see all sub-arrays :
SELECT S3.TID, S3.TName
FROM tab
CROSS APPLY OPENJSON(JsonData)
WITH ( S nvarchar(max) '$.S' AS JSON) AS S0
CROSS APPLY OPENJSON (S0.S)
WITH (
SP nvarchar(max) '$.SP' AS JSON ) S1
CROSS APPLY OPENJSON (S1.SP)
WITH (
TP nvarchar(max) '$.TP' AS JSON ) S2
CROSS APPLY OPENJSON (S2.TP)
WITH (
TID nvarchar(500) '$.TID',
TName nvarchar(500) '$.TName' ) S3
Demo
Update : If the first array S is fixed to contain only one item, we can reduce one-step as
SELECT S3.TID, S3.TName
FROM tab
CROSS APPLY OPENJSON(JsonData)
WITH (
SP nvarchar(max) '$.S[0].SP' AS JSON ) S1
CROSS APPLY OPENJSON (S1.SP)
WITH (
TP nvarchar(max) '$.TP' AS JSON ) S2
CROSS APPLY OPENJSON (S2.TP)
WITH (
TID nvarchar(500) '$.TID',
TName nvarchar(500) '$.TName' ) S3
Demo

Parse JSON structure in SQL

I have written a code that reads information from JSON lines to table in SQL:
declare #pJSON varchar(max) = '
{
"School": "MiddleSchool",
"Password": "SchoolPassword",
"Attributes": [
{
"Type": "Exam",
"Value": "1"
},
{
"Type": "Class",
"Value": "11b"
},
{
"Type": "Math",
"Value": [
{
"ExamDate": "2019-01-01",
"Points": 100,
"Grade": 10,
"Notes": "Good"
}
]
}
]
} '
select ExamDate, Points, Grade, Notes
from OPENJSON(#pJSON, N'$.Attributes[2].Value')
cross apply openjson ([Value])
with
(
ExamDate date,
Points int,
Grade int,
Notes varchar(max)
) as [value]
Code works fine, but I really hate N'$.Attributes[2].Value' part. Exam information can be in the first, second, third place, so [2] doesn't really work for me. Do you have any suggestions for me, how I can improve this code? Thank you!
You could use JSON_QUERY:
select ExamDate, Points, Grade, Notes
from OPENJSON(JSON_QUERY(#pJSON, N'$.Attributes'))
with
(
ExamDate date N'$.Value[0].ExamDate', -- here 0 because Value is array too
Points int N'$.Value[0].Points',
Grade int N'$.Value[0].Grade',
Notes varchar(max) N'$.Value[0].Notes'
) as [value]
WHERE ExamDate IS NOT NULL;
db<>fiddle demo
EDIT:
In original question there was only one exam in array. If array could contain more than code should be adjusted:
SELECT s2.[key]
,ExamValue = JSON_VALUE(s2.value, '$.ExamDate')
,Points = JSON_VALUE(s2.value, '$.Points')
,Grade = JSON_VALUE(s2.value, '$.Grade')
,Notes = JSON_VALUE(s2.value, '$.Notes')
FROM OPENJSON(JSON_QUERY(#pJSON, N'$.Attributes')) s
CROSS APPLY OPENJSON(JSON_QUERY(s.value, N'$.Value')) s2;
-- or
SELECT [value].*
FROM OPENJSON(JSON_QUERY(#pJSON, N'$.Attributes'))
CROSS APPLY OPENJSON(JSON_QUERY(value, N'$.Value'))
with
(
ExamDate date N'$.ExamDate',
Points int N'$.Points',
Grade int N'$.Grade',
Notes varchar(max) N'$.Notes'
) as [value];
db<>fiddle demo