generating json from bad mysql-formatted dates in asp - sql

I was thrown in a new project, which is apparently more than just oudated. The application saves opening hours in a very weird pattern in the DB and this is driving me crazy for over a week now.
Please have a look at this image:
As you might see, the opening hours are saved in a pattern like:
dayFrom | dayTo | timeFrom | timeTo
=======================================
monday | friday | 07:00 | 17:00
saturday | | 08:00 | 12:00
Just to prevent any misunderstanding:
Open MO - FR from 07:00 to 17:00
Open SA from 08:00 to 12:00
Closed on Sunday
Now, this seems to be kinda off already, but sticking with that, a table could look like this:
dayFrom | dayTo | timeFrom | timeTo
=======================================
monday | tuesday | 07:00 | 14:00
wednesday | | 08:00 | 12:00
thursday | friday | 07:30 | 13:00
saturday | | 08:00 | 12:00
So, now my problem: I need to make a loop (or something like this) to create a valid json-string, containing all these opening hours.
Right now, I have this:
jsonAppendix = "{""openingHours"":["
for i = 1 To cint(hoechsterTag)
jsonAppendix = jsonAppendix & "{""dayOfWeek"":" & i & ", ""from1"":""" & rs("ZeitVon") & """, ""to1"":""" & rs("ZeitBis") & """},"
next
'Remove last comma
jsonAppendix = LEFT(jsonAppendix, (LEN(jsonAppendix)-1))
jsonAppendix = jsonAppendix & "]}"
If I have only a "monday-friday", it works already, but the 2nd (or next entries) aren't taken into account.
The output looks like this, which is apparently kinda correct:
{
"openingHours":[
{
"dayOfWeek":1,
"from1":"07:00",
"to1":"17:00"
},
{
"dayOfWeek":2,
"from1":"07:00",
"to1":"17:00"
},
{
"dayOfWeek":3,
"from1":"07:00",
"to1":"17:00"
},
{
"dayOfWeek":4,
"from1":"07:00",
"to1":"17:00"
},
{
"dayOfWeek":5,
"from1":"07:00",
"to1":"17:00"
}
]
}
But the "Saturday" is not being recognized.
My function looks like this:
SQL = "SELECT * FROM StandortOpen WHERE S_ID = " & iStandortId & " AND OpenArt = '" & sArt & "' ORDER BY Sort,OpenArt DESC"
call openRS(SQL)
'day-mapping
tageV(0) = replace(rs("TagVon"),"Mo", 1)
tageV(1) = replace(rs("TagVon"),"Di", 2)
tageV(2) = replace(rs("TagVon"),"Mi", 3)
tageV(3) = replace(rs("TagVon"),"Do", 4)
tageV(4) = replace(rs("TagVon"),"Fr", 5)
tageV(5) = replace(rs("TagVon"),"Sa", 6)
tageV(6) = 7
tageB(0) = replace(rs("TagBis"),"Mo", 1)
tageB(1) = replace(rs("TagBis"),"Di", 2)
tageB(2) = replace(rs("TagBis"),"Mi", 3)
tageB(3) = replace(rs("TagBis"),"Do", 4)
tageB(4) = replace(rs("TagBis"),"Fr", 5)
tageB(5) = replace(rs("TagBis"),"Sa", 6)
'for example: mo - fr
for each item in tageV
'save smallest weekday
if(isNumeric(item) AND item > "") then
if(cint(item) <= cint(niedrigsterTag)) then
niedrigsterTag = cint(item)
end if
end if
next
for each item in tageB
'save highest weekday
if(isNumeric(item) AND item > "") then
if(cint(item) >= cint(hoechsterTag)) then
hoechsterTag = cint(item)
end if
end if
next
And the openRS()-Function:
sub openRS(str_sql)
'Response.write "SQL: " & str_sql & "<br>"
set rs = CreateObject("ADODB.Recordset")
rs.open str_sql,conn,1,3
end sub
So basically: Mapping numbers to the days, iterating through (or compare them to get a timespan).
I'm using a RecordSet as well. Maybe I need to use arrays or something like this? Any help would be really appreciated.
I can't alter the table nor the design of that, I have to stick with that gargabe

If you want to create the dataset in SQL Server, consider the following
Example
Declare #YourTable table (dayFrom varchar(25),dayTo varchar(25),timeFrom varchar(25),timeTo varchar(25))
Insert Into #YourTable values
('monday' ,'tuesday','07:00','14:00'),
('wednesday','' ,'08:00','12:00'),
('thursday' ,'friday' ,'07:30','13:00'),
('saturday' ,'' ,'08:00','12:00')
;with cteD as (Select * From (Values(1,'Monday'),(2,'Tuesday'),(3,'Wednesday'),(4,'Thursday'),(5,'Friday'),(6,'Saturday'),(7,'Sunday')) DDD(DD,DDD) ),
cteR as (
Select A.*
,R1 = B.DD
,R2 = IsNull(C.DD,B.DD)
From #YourTable A
Left Join cteD B on dayFrom = B.DDD
Left Join cteD C on dayTo = C.DDD
Where 1=1 -- Your WHERE STATEMENT HERE
)
Select daySeq = A.DD
,dayOfWeek = A.DDD
,from1 = IsNull(B.TimeFrom,'Closed')
,from2 = IsNull(B.TimeTo,'Closed')
From cteD A
Left Join cteR B on A.DD between B.R1 and B.R2
Order By 1
Returns
Note: The Closed is Optional. Remove the "LEFT" Join in the final query
Now, if you want to create the JSON String in SQL Server, and you're NOT on 2016, we can tweak the final query and add a UDF.
Select JSON=[dbo].[udf-Str-JSON](0,0,(
Select daySeq = A.DD
,dayOfWeek = A.DDD
,from1 = IsNull(B.TimeFrom,'Closed')
,from2 = IsNull(B.TimeTo,'Closed')
From cteD A
Left Join cteR B on A.DD between B.R1 and B.R2
Order By 1
For XML RAW
))
Returned JSON String
[{
"daySeq": "1",
"dayOfWeek": "Monday",
"from1": "07:00",
"from2": "14:00"
}, {
"daySeq": "2",
"dayOfWeek": "Tuesday",
"from1": "07:00",
"from2": "14:00"
}, {
"daySeq": "3",
"dayOfWeek": "Wednesday",
"from1": "08:00",
"from2": "12:00"
}, {
"daySeq": "4",
"dayOfWeek": "Thursday",
"from1": "07:30",
"from2": "13:00"
}, {
"daySeq": "5",
"dayOfWeek": "Friday",
"from1": "07:30",
"from2": "13:00"
}, {
"daySeq": "6",
"dayOfWeek": "Saturday",
"from1": "08:00",
"from2": "12:00"
}, {
"daySeq": "7",
"dayOfWeek": "Sunday",
"from1": "Closed",
"from2": "Closed"
}]
The UDF if Interested
CREATE FUNCTION [dbo].[udf-Str-JSON] (#IncludeHead int,#ToLowerCase int,#XML xml)
Returns varchar(max)
AS
Begin
Declare #Head varchar(max) = '',#JSON varchar(max) = ''
; with cteEAV as (Select RowNr =Row_Number() over (Order By (Select NULL))
,Entity = xRow.value('#*[1]','varchar(100)')
,Attribute = xAtt.value('local-name(.)','varchar(100)')
,Value = xAtt.value('.','varchar(max)')
From #XML.nodes('/row') As R(xRow)
Cross Apply R.xRow.nodes('./#*') As A(xAtt) )
,cteSum as (Select Records=count(Distinct Entity)
,Head = IIF(#IncludeHead=0,IIF(count(Distinct Entity)<=1,'[getResults]','[[getResults]]'),Concat('{"status":{"successful":"true","timestamp":"',Format(GetUTCDate(),'yyyy-MM-dd hh:mm:ss '),'GMT','","rows":"',count(Distinct Entity),'"},"retults":[[getResults]]}') )
From cteEAV)
,cteBld as (Select *
,NewRow=IIF(Lag(Entity,1) over (Partition By Entity Order By (Select NULL))=Entity,'',',{')
,EndRow=IIF(Lead(Entity,1) over (Partition By Entity Order By (Select NULL))=Entity,',','}')
,JSON=Concat('"',IIF(#ToLowerCase=1,Lower(Attribute),Attribute),'":','"',Value,'"')
From cteEAV )
Select #JSON = #JSON+NewRow+JSON+EndRow,#Head = Head From cteBld, cteSum
Return Replace(#Head,'[getResults]',Stuff(#JSON,1,1,''))
End
-- Parameter 1: #IncludeHead 1/0
-- Parameter 2: #ToLowerCase 1/0 (converts field name to lowercase
-- Parameter 3: (Select * From ... for XML RAW)
-- Syntax : Select [dbo].[udf-Str-JSON](0,1,(Select Top 2 RN=Row_Number() over (Order By (Select NULL)),* from [Chinrus-Shared].[dbo].[ZipCodes] Where StateCode in ('RI') for XML RAW))
/*
Declare #User table (ID int,Active bit,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50))
Insert into #User values
(1,1,'John','Smith','john.smith#email.com'),(2,0,'Jane','Doe' ,'jane.doe#email.com')
Declare #XML xml = (Select * from #User for XML RAW)
Select A.ID
,B.JSON
From #User A
Cross Apply (Select JSON=[dbo].[udf-Str-JSON](0,0,(Select A.* For XML Raw)) ) B
*/

Related

Query key values in a json column

I have a table "jobs" with one of the columns called "check_list" ( varchar(max) that has JSON values, an example value would be
{
"items":[
{
"name":"machine 1",
"state":"",
"comment":"",
"isReleaseToProductionCheck":true,
"mnachine_id":10
},
{
"name":"machine 2",
"state":"",
"comment":"",
"isReleaseToProductionCheck":true,
"machine_id":12
}
]
}
Now how would I write a SQL query to only return the rows where the column "check_list" has items[machine_id] = 12
In the end after some trial and error this was the solution that worked for me. I had to add the ISJSON check because some of the older data was invalid
WITH jobs (id, workorder, selectedMachine) AS(
SELECT
[id],
[workorder],
(
select
*
from
openjson(check_list, '$.items') with (machine_id int '$.machine_id')
where
machine_id = 12
) as selectedMachine
FROM
engineering_job_schedule
WHERE
ISJSON(check_list) > 0
)
Select
*
from
jobs
where
selectedMachine = 12

subquery results appends to all main query selected field

I'm writing a stored procedure to get list of IOT parameter data under a specific machine and the result of stored procedure should have a specific JSON format. the problem is, when I tried to add a parameter data under another machine I found out the subquery result append all its results under all machines. I want to Alter the query so each machine should have just its parameter data under it and not changing the JSON format.
This is the Stored procedure:
declare #jsonTwo nvarchar(max)=(
Select JSON_QUERY((
select CAST((
select
MAE.MachineName as MachineName
,
(select IOTR.MachineCode, IOTP.IotParameterName, IOTR.CreatedAt, datename(WEEKDAY, IOTR.CreatedAt) as FilterRange,
avg(IOTP.IotParameterValue) as ParameterValue,MP.UpperControlLimit , MP.LowerControlLimit
from IOTMachineParameters IOTP
inner join IOTMachineReadings IOTR ON IOTP.IotMachineID = IOTR.Id
inner join MachineAndEquipments MAE on MAE.MachineCode = IOTR.MachineCode
inner join MachineParameters MP on IOTP.IotParameterName = MP.ParamterName
where
MP.ParameterType = 'PARAMETERIZED'
and IotP.IsChecked = 1
and IOTR.CompanyCode = 'DA-1663079927040'
and MAE.MachineCode = IOTR.MachineCode
and IOTP.IotMachineID = IOTR.Id
and IOTR.CreatedAt >= '2022-09-01' and IOTR.CreatedAt <= '2022-11-16 10:11:00.0000000'
group by IOTR.MachineCode,IOTP.IotParameterName,IOTR.CreatedAt,datename(WEEKDAY, IOTR.CreatedAt),MAE.MachineName,MP.LowerControlLimit,MP.UpperControlLimit
for json path) as MachineReadings
from MachineAndEquipments MAE inner join IOTMachineReadings IOTR ON MAE.MachineCode = IOTR.MachineCode
inner join IOTMachineParameters IOTP ON IOTP.IotMachineID = IOTR.Id
where MAE.CompanyId = 'DA-1663079927040'
and IOTP.IotMachineID = IOTR.Id
group by MAE.MachineName
for json path ,Include_null_values)as nvarchar(max))as part1 for json path, without_array_wrapper)));
select #jsonTwo as data
when i run the MachineReadings subquery it returns all the records
reults of MachineReadings subquery
The tables are:
Tables of the query
so is there a way to like filter out the subquery results based on the outer selection of Machine Name.
I expected each object, has Machine name and a list of IOT parameter reading data under this machine name only. Instead I found that each Machine name has the same exact list of IOT parameter reading data
Targeted JSON format:
{
"part1":[
{
"MachineName":"Machine X",
"MachineReadings":[
{
"MachineCode":"Machine-012",
"MachineName":"Machine X",
"IotParameterName":"t",
"CreatedAt":"2022-11-14T11:11:42",
"FilterRange":"Monday",
"ParameterValue":20.000000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
}
]
},
{
"MachineName":"Machine Y",
"MachineReadings":[
{
"MachineCode":"Machine-789",
"MachineName":"Machine Y",
"IotParameterName":"a test",
"CreatedAt":"2022-11-16T10:11:00",
"FilterRange":"Wednesday",
"ParameterValue":3.000000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
},
{
"MachineCode":"Machine-789",
"MachineName":"Machine Y",
"IotParameterName":"new parameter",
"CreatedAt":"2022-11-15T10:09:51",
"FilterRange":"Tuesday",
"ParameterValue":13.500000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
}
]
}
]
}
This is The Resulted JSON Format:
{
"part1":[
{
"MachineName":"rtyy",
"MachineCode":"Machine-012",
"MachineReadings":[
{
"MachineCode":"Machine-012",
"MachineName":"rtyy",
"IotParameterName":"t",
"CreatedAt":"2022-11-14T11:11:42",
"FilterRange":"Monday",
"ParameterValue":20.000000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
},
{
"MachineCode":"Machine-789",
"MachineName":"the other 789",
"IotParameterName":"a test",
"CreatedAt":"2022-11-16T10:11:00",
"FilterRange":"Wednesday",
"ParameterValue":3.000000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
},
{
"MachineCode":"Machine-789",
"MachineName":"the other 789",
"IotParameterName":"new parameter",
"CreatedAt":"2022-11-15T10:09:51",
"FilterRange":"Tuesday",
"ParameterValue":13.500000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
}
]
},
{
"MachineName":"the other 789",
"MachineCode":"Machine-789",
"MachineReadings":[
{
"MachineCode":"Machine-012",
"MachineName":"rtyy",
"IotParameterName":"t",
"CreatedAt":"2022-11-14T11:11:42",
"FilterRange":"Monday",
"ParameterValue":20.000000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
},
{
"MachineCode":"Machine-789",
"MachineName":"the other 789",
"IotParameterName":"a test",
"CreatedAt":"2022-11-16T10:11:00",
"FilterRange":"Wednesday",
"ParameterValue":3.000000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
},
{
"MachineCode":"Machine-789",
"MachineName":"the other 789",
"IotParameterName":"new parameter",
"CreatedAt":"2022-11-15T10:09:51",
"FilterRange":"Tuesday",
"ParameterValue":13.500000,
"UpperControlLimit":0.00,
"LowerControlLimit":0.00
}
]
}
]
}
The issue could be there's no relationship between the correlated subquery MachineReadings and tables in outer query FROM clause. Thus, the result of MachineReadings is applied to every row returned by outer query.
Formatted your code below for easy reference:
declare #jsonTwo nvarchar(max)=(
Select
JSON_QUERY((
select
CAST((
select
MAE.MachineName as MachineName
,
(
select
IOTR.MachineCode,
IOTP.IotParameterName,
IOTR.CreatedAt,
datename(WEEKDAY, IOTR.CreatedAt) as FilterRange,
avg(IOTP.IotParameterValue) as ParameterValue,
MP.UpperControlLimit ,
MP.LowerControlLimit
from
IOTMachineParameters IOTP
inner join IOTMachineReadings IOTR ON
IOTP.IotMachineID = IOTR.Id
inner join MachineAndEquipments MAE on
MAE.MachineCode = IOTR.MachineCode
inner join MachineParameters MP on
IOTP.IotParameterName = MP.ParamterName
where
MP.ParameterType = 'PARAMETERIZED'
and IotP.IsChecked = 1
and IOTR.CompanyCode = 'DA-1663079927040'
and MAE.MachineCode = IOTR.MachineCode
and IOTP.IotMachineID = IOTR.Id
and IOTR.CreatedAt >= '2022-09-01'
and IOTR.CreatedAt <= '2022-11-16 10:11:00.0000000'
group by
IOTR.MachineCode,
IOTP.IotParameterName,
IOTR.CreatedAt,
datename(WEEKDAY, IOTR.CreatedAt),
MAE.MachineName,
MP.LowerControlLimit,
MP.UpperControlLimit
for json path) as MachineReadings
from
MachineAndEquipments MAE
inner join IOTMachineReadings IOTR ON
MAE.MachineCode = IOTR.MachineCode
inner join IOTMachineParameters IOTP ON
IOTP.IotMachineID = IOTR.Id
where
MAE.CompanyId = 'DA-1663079927040'
and IOTP.IotMachineID = IOTR.Id
group by
MAE.MachineName
for json path ,
Include_null_values)as nvarchar(max))as part1 for json path,
without_array_wrapper)));
select #jsonTwo as data

Safe casting a regexp match from REGEXP_REPLACE

I have a table with some code points (e.g. &#38) which I want to strip out from a text value in BigQuery.
My strategy is to use a regexp replace on the number replacing the number with the valid character.
If I try:
WITH items as (SELECT "Test & " as item)
SELECT
CODE_POINTS_TO_STRING([SAFE_CAST(REGEXP_EXTRACT(item, r"&#([0-9]{2})") AS INT64)]) as test_replace
FROM items
This will produce the output that I want for the entry
[
{
"test_replace": "&"
}
]
If I try:
WITH items as (SELECT "Test & " as item)
SELECT
REGEXP_REPLACE(
item,
r"&#([0-9]{2});",
CODE_POINTS_TO_STRING([SAFE_CAST("\\1" as INT64)])
) as full_replace
FROM items
This will produce a null output
[
{
"full_replace": null
}
]
However if I hard code the value in:
WITH items as (SELECT "Test & " as item)
SELECT
REGEXP_REPLACE(
item,
r"&#([0-9]{2});",
CODE_POINTS_TO_STRING([SAFE_CAST("38" as INT64)])
) as full_replace
FROM items
This works.
[
{
"full_replace": "Test & "
]
I know that the regexp is evaluating correctly as if I try:
WITH items as (SELECT "Test & " as item)
SELECT
REGEXP_REPLACE(
item,
r"&#([0-9]{2});",
CONCAT("\\1", "test")
) as part_replace
FROM ITEMS
This will return:
[
{
"part_replace": "Test 38test "
}
]
My question is therefore, how do I get the SAFE_CAST() Function to evaluate the regexp match (it seems to be evaluating the string literal).
I have a table with some code points (e.g. &#38) which I want to strip out from a text value in BigQuery.
Try approach as in below example
#standardSQL
CREATE TEMP FUNCTION multiReplace(item STRING, arr ARRAY<STRUCT<x STRING, y STRING>>)
RETURNS STRING
LANGUAGE js AS """
for (i = 0; i < arr.length; i++) {
item = item.replace(arr[i].x, arr[i].y)
};
return item;
""";
WITH items AS (
SELECT "Test & abc ' xyz" AS item UNION ALL
SELECT "abc xyz"
)
SELECT item, multiReplace(item, points) full_replace
FROM (
SELECT
item,
ARRAY(
SELECT AS STRUCT val, CODE_POINTS_TO_STRING([SAFE_CAST(SUBSTR(val, -3, 2) AS INT64)]) point
FROM UNNEST(REGEXP_EXTRACT_ALL(item, r'(&#[0-9]{2};)')) val
) points
FROM items
)
with result
Row item full_replace
1 Test & abc ' xyz Test & abc ' xyz
2 abc xyz abc xyz
Option 2
While the simplest way to approach above is
#standardSQL
CREATE TEMP FUNCTION multiReplace(item STRING)
RETURNS STRING
LANGUAGE js AS """
var decodeHtmlEntity = function(str) {
return str.replace(/&#([0-9]{2});/g, function(match, dec) {
return String.fromCharCode(dec);
});
};
return decodeHtmlEntity(item);
""";
WITH items AS (
SELECT "Test & abc ' xyz" AS item UNION ALL
SELECT "abc xyz"
)
SELECT item, multiReplace(item) full_replace
FROM items
with the same output

How to structure JSON SQL by row using values from the row?

I'm struggling to structure JSON using SQL.
Say I have a table like this:
| col1 | col2 | col3 |
+---------------+----------+----------+
| specialvalue | someval | someval |
| specialvalue2 | someval2 | someval2 |
| | | |
I'm trying to get a structure like the following:
{
"specialvalue": {
"specialcol": "specialvalue",
"col2": "someval",
"col3": "someval"
},
"specialvalue2": {
"specialcol": "specialvalue2",
"col2": "someval2",
"col3": "someval2"
}
}
How can I accomplish this? Can I use JSON_MODIFY with dynamic keys, while mapping through every row in the set?
The closest I've gotten is the following:
SELECT
specialcol,
col2,
col3
INTO #tmpTbl
FROM myTable
SELECT
specialcol,
(SELECT * FROM #tmpTbl FOR JSON AUTO) as 'Value'
FROM #tmpTbl
FOR JSON AUTO
DROP TABLE #tmp
Which returns the following:
{
"specialcol":"specialvalue",
"Value":{
"col1": "specialvalue",
"col2": "someval",
"col3": "someval"
},
"specialcol":"specialvalue2",
"Value":{
"col1": "specialvalue2",
"col2": "someval2",
"col3": "someval2"
}
}
Which is close, but not quite what I need.
Is there a way to use JSON_MODIFY to accomplish what I'm trying to get?
From my comment and thinking about this. Not the most elegant, but could potential get you there.
Inline query to get the results in json, then wrap those results based on the value from your col1 as the key. Put it all together comma delimited and then a final wrap in brackets.
DECLARE #TestData TABLE
(
[col1] NVARCHAR(100)
, [col2] NVARCHAR(100)
, [col3] NVARCHAR(100)
);
DECLARE #JsonValue NVARCHAR(MAX) = '';
INSERT INTO #TestData (
[col1]
, [col2]
, [col3]
)
VALUES ( 'specialvalue', 'someval', 'someval' )
, ( 'specialvalue2', 'someval2', 'someval2' );
SELECT #JsonValue = #JsonValue + N'"' + [a].[col1] + N'": '
+ (
SELECT [aa].[col1] AS 'specialvalue'
, [aa].[col2] AS 'col2'
, [aa].[col3] AS 'col3'
FROM #TestData [aa]
WHERE [aa].[col1] = [a].[col1]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) + N','
FROM #TestData [a];
SET #JsonValue = N'{' + SUBSTRING(#JsonValue, 1, LEN(#JsonValue) - 1) + N'}';
SELECT #JsonValue;
Gets you this:
{
"specialvalue": {
"specialvalue": "specialvalue",
"col2": "someval",
"col3": "someval"
},
"specialvalue2": {
"specialvalue": "specialvalue2",
"col2": "someval2",
"col3": "someval2"
}
}
SQL Server 2017 -
;WITH cte as (
select 'specialvalue' as specialcol, 'someval' col2, 'someval' col3 union
select 'specialvalue2' as specialcol, 'someval2' col2, 'someval2' col3 )
SELECT
CASE WHEN specialcol = 'specialvalue' THEN specialcol END as [specialvalue.specialcol],
CASE WHEN specialcol = 'specialvalue' THEN col2 END as [specialvalue.col2],
CASE WHEN specialcol = 'specialvalue' THEN col3 END as [specialvalue.col3],
CASE WHEN specialcol = 'specialvalue2' THEN specialcol END as [specialvalue2.specialcol],
CASE WHEN specialcol = 'specialvalue2' THEN col2 END as [specialvalue2.col2],
CASE WHEN specialcol = 'specialvalue2' THEN col3 END as [specialvalue2.col3]
FROM cte
FOR JSON PATH
Output:
{
"specialvalue":{
"specialcol":"specialvalue",
"col2":"someval",
"col3":"someval"
}
},
{
"specialvalue2":{
"specialcol":"specialvalue2",
"col2":"someval2",
"col3":"someval2"
}
}

JSON pairs to rows for existing json columns

With the help of #UnhandledExcepSean (Json pairs to rows) I was able to get an idea how to turn my json key/value pairs into rows. It was not as easy as I thought. However, I still have an issue. I was I was able to see how it can be done here:
I wanted it to look something like this:
+-----------+-------+------------+-----------+-------+------------------+---------+-----+-------+-------+---------+
| DateTime | Side | Identifier | Color | Level | SDSa | Current | LEF | Sys | Membr | SDS |
+-----------+-------+------------+-----------+-------+------------------+---------+-----+-------+-------+---------+
| 10/1/2018 | 15:01 | Left | 107604736 | Red | 0.65 5.053539157 | 0 | 0 | BOBJ7 | 5 | 1 |
| 10/2/2018 | 15:01 | Left | 107604737 | Red | 0.65 5.053539157 | 0.3035 | 1 | BOBJ8 | 6 | 0.98962 |
| 10/3/2018 | 15:01 | Left | 107604738 | Red | 0.65 5.053539157 | 0.6070 | 2 | BOBJ9 | 7 | 0.96576 |
+-----------+-------+------------+-----------+-------+------------------+---------+-----+-------+-------+---------+
I have found out how to manipulate the document when it is stored in a variable. I just cannot get find that balance or answer to how to use my same query for the json that is stored in a db in a column instead.
Here is an example of the document:
{
"DateTime": "10/1/2018 3:01:01 PM",
"Side": "Left",
"Identifier": "107604736",
"Color": "Red",
"Level": 0.65,
"SDSa": 5.0535391569137573,
"LEF": 0.0,
"System": "BOBJ7",
"Membrane": 5,
"Current": [
0.0,
0.303535521,
0.607071042,
0.910606563,
1.21414208,
1.51767755,
1.82121313,
2.12474871,
2.42828417,
2.73181963,
3.035355,
3.33889079,
3.64242625,
3.94596171,
4.24949741,
4.553033,
4.85656834,
5.160104,
5.46363926,
5.76717472,
6.07071,
6.374246,
6.67778158,
6.981317,
7.2848525,
7.588388,
7.89192343,
8.195459,
8.498995,
8.80253,
9.106066,
9.409601,
9.713137,
10.0166721,
10.3202076,
10.6237431,
10.9272785,
11.230814,
11.5343494,
11.8378849,
12.14142,
12.4449568,
12.7484922,
13.0520277,
13.3555632,
13.6590986,
13.9626341,
14.26617,
14.569705,
14.87324,
15.1767759,
15.4803114,
15.7838469,
16.0873833,
16.3909187,
16.6944542,
16.99799,
17.3015251,
17.60506,
17.908596,
18.2121315,
18.515667,
18.8192024,
19.1227379,
19.4262733,
19.7298088,
20.0333443,
20.33688,
20.6404152,
20.94395,
21.2474861,
21.5510216,
21.854557,
22.1580925,
22.461628,
22.7651634,
23.0686989,
23.3722343,
23.67577,
23.9793053,
24.28284,
24.5863781,
24.8899136,
25.193449,
25.4969845,
25.80052,
26.1040554,
26.40759,
26.7111263,
27.0146618,
27.3181973,
27.6217327,
27.9252682,
28.2288036,
28.53234,
28.8358746,
29.13941,
29.4429455,
29.74648,
30.0500164
],
"Measurements": [
{
"FPOS": 1,
"Orient": "H",
"SDS50": 6.8644590377807617,
"ImageN": 0,
"SDS": [
1.0,
0.9896224,
0.9657684,
0.937525332,
0.9123899,
0.888601959,
0.8634422,
0.8382806,
0.8161909,
0.7984247,
0.7806436,
0.7606637,
0.739305735,
0.720110357,
0.7029224,
0.6836812,
0.660055459,
0.6333771,
0.6086391,
0.5865341,
0.5649619,
0.540699542,
0.5150109,
0.4912444,
0.470531732,
0.4510031,
0.429589,
0.407328546,
0.386515945,
0.369066834,
0.353259325,
0.336980551,
0.3197548,
0.302164435,
0.2844041,
0.264812022,
0.2432023,
0.221351326,
0.203265771,
0.190894246,
0.183355331,
0.178263873,
0.17374523,
0.169159114,
0.1635048,
0.15626812,
0.148360759,
0.141854659,
0.1383282,
0.136285663,
0.133377567,
0.127650827,
0.119844966,
0.111289464,
0.103005029,
0.09480265,
0.0866060555,
0.07927561,
0.0740468055,
0.07167137,
0.07141984,
0.07215432,
0.07259899,
0.07151956,
0.0681445152,
0.06242689,
0.05562524,
0.0492420681,
0.04441181,
0.0410645567,
0.0388742052,
0.0380086526,
0.03860841,
0.04033492,
0.04170464,
0.04166763,
0.0399215743,
0.0370087326,
0.0335897,
0.0301406663,
0.02666917,
0.023069948,
0.0193837862,
0.0161479469,
0.0140230907,
0.0133305294,
0.0137383873,
0.0145777585,
0.0155265825,
0.0166243,
0.01805606,
0.01932042,
0.0196347721,
0.01826151,
0.0154753188,
0.012052347,
0.008844916,
0.00625393027,
0.004384732,
0.00334442779
],
"Processed": false
},
{
"FPOS": 2,
"Orient": "H",
"SDS50": 3.2426192760467529,
"ImageN": 0,
"SDS": [
1.0,
0.984369457,
0.940739632,
0.8834237,
0.8255927,
0.7736917,
0.7277459,
0.681687,
0.6329853,
0.582352459,
0.5328522,
0.48483035,
0.436798245,
0.388586164,
0.3424556,
0.302069068,
0.267472,
0.237092659,
0.209047124,
0.184123,
0.163114548,
0.144511625,
0.126265839,
0.107269846,
0.08942619,
0.07420107,
0.06193066,
0.0517099164,
0.0435060449,
0.0383287631,
0.0352067538,
0.03245497,
0.0286534447,
0.0242379941,
0.0201460086,
0.016266821,
0.0121985339,
0.008013846,
0.00560544431,
0.00502379332,
0.004533774,
0.004487538,
0.00551742641,
0.007546712,
0.009179788,
0.009129186,
0.007475236,
0.005305866,
0.004060863,
0.00462530646,
0.00631512143,
0.00748074846,
0.007632819,
0.006844715,
0.00562061928,
0.005166012,
0.006103046,
0.00768285431,
0.009006567,
0.009526576,
0.009514096,
0.009059127,
0.008065625,
0.006526997,
0.00434135273,
0.00191119267,
0.00254829624,
0.006861757,
0.0108742379,
0.0131905386,
0.013858974,
0.0132871456,
0.012235119,
0.01142512,
0.01094334,
0.0107232835,
0.0107062105,
0.010995524,
0.0112270387,
0.0102753676,
0.00612402242,
0.0010008571,
0.00318561238,
0.009038351,
0.0119382814,
0.0132263815,
0.013723935,
0.0133564435,
0.0129926438,
0.0127558094,
0.011888911,
0.009955382,
0.00670363754,
0.00246145763,
0.000897339836,
0.0037357898,
0.006457583,
0.007566943,
0.007532189,
0.006015837
],
"Processed": false
}}
You JSON-object has some easy to query values in the first level.
Furthermore, there is an array of values called Current, and there is more: There is an object called Measurements, which is an array of objects by its own. And still there is more: The objects within Measurements contain an array of values themselves, called SDS.
Assumably you won't be happy with a flat give-me-everything query. This would lead to very many rows with repeating columns all over...
Try it out (I create a mockup-table to simulate your needs):
DECLARE #mockupTable TABLE (ID INT IDENTITY,YourJson NVARCHAR(MAX));
INSERT INTO #mockupTable VALUES
(N'{
"DateTime": "10/1/2018 3:01:01 PM",
"Side": "Left",
"Identifier": "107604736",
"Color": "Red",
"Level": 0.65,
"SDSa": 5.0535391569137573,
"LEF": 0.0,
"System": "BOBJ7",
"Membrane": 5,
"Current": [
0.0,
0.303535521,
0.607071042,
0.910606563,
1.21414208,
1.51767755,
1.82121313,
2.12474871,
2.42828417,
2.73181963,
3.035355,
3.33889079,
3.64242625,
3.94596171,
4.24949741,
4.553033,
4.85656834,
5.160104,
5.46363926,
5.76717472,
6.07071,
6.374246,
6.67778158,
6.981317,
7.2848525,
7.588388,
7.89192343,
8.195459,
8.498995,
8.80253,
9.106066,
9.409601,
9.713137,
10.0166721,
10.3202076,
10.6237431,
10.9272785,
11.230814,
11.5343494,
11.8378849,
12.14142,
12.4449568,
12.7484922,
13.0520277,
13.3555632,
13.6590986,
13.9626341,
14.26617,
14.569705,
14.87324,
15.1767759,
15.4803114,
15.7838469,
16.0873833,
16.3909187,
16.6944542,
16.99799,
17.3015251,
17.60506,
17.908596,
18.2121315,
18.515667,
18.8192024,
19.1227379,
19.4262733,
19.7298088,
20.0333443,
20.33688,
20.6404152,
20.94395,
21.2474861,
21.5510216,
21.854557,
22.1580925,
22.461628,
22.7651634,
23.0686989,
23.3722343,
23.67577,
23.9793053,
24.28284,
24.5863781,
24.8899136,
25.193449,
25.4969845,
25.80052,
26.1040554,
26.40759,
26.7111263,
27.0146618,
27.3181973,
27.6217327,
27.9252682,
28.2288036,
28.53234,
28.8358746,
29.13941,
29.4429455,
29.74648,
30.0500164
],
"Measurements": [
{
"FPOS": 1,
"Orient": "H",
"SDS50": 6.8644590377807617,
"ImageN": 0,
"SDS": [
1.0,
0.9896224,
0.9657684,
0.937525332,
0.9123899,
0.888601959,
0.8634422,
0.8382806,
0.8161909,
0.7984247,
0.7806436,
0.7606637,
0.739305735,
0.720110357,
0.7029224,
0.6836812,
0.660055459,
0.6333771,
0.6086391,
0.5865341,
0.5649619,
0.540699542,
0.5150109,
0.4912444,
0.470531732,
0.4510031,
0.429589,
0.407328546,
0.386515945,
0.369066834,
0.353259325,
0.336980551,
0.3197548,
0.302164435,
0.2844041,
0.264812022,
0.2432023,
0.221351326,
0.203265771,
0.190894246,
0.183355331,
0.178263873,
0.17374523,
0.169159114,
0.1635048,
0.15626812,
0.148360759,
0.141854659,
0.1383282,
0.136285663,
0.133377567,
0.127650827,
0.119844966,
0.111289464,
0.103005029,
0.09480265,
0.0866060555,
0.07927561,
0.0740468055,
0.07167137,
0.07141984,
0.07215432,
0.07259899,
0.07151956,
0.0681445152,
0.06242689,
0.05562524,
0.0492420681,
0.04441181,
0.0410645567,
0.0388742052,
0.0380086526,
0.03860841,
0.04033492,
0.04170464,
0.04166763,
0.0399215743,
0.0370087326,
0.0335897,
0.0301406663,
0.02666917,
0.023069948,
0.0193837862,
0.0161479469,
0.0140230907,
0.0133305294,
0.0137383873,
0.0145777585,
0.0155265825,
0.0166243,
0.01805606,
0.01932042,
0.0196347721,
0.01826151,
0.0154753188,
0.012052347,
0.008844916,
0.00625393027,
0.004384732,
0.00334442779
],
"Processed": false
},
{
"FPOS": 2,
"Orient": "H",
"SDS50": 3.2426192760467529,
"ImageN": 0,
"SDS": [
1.0,
0.984369457,
0.940739632,
0.8834237,
0.8255927,
0.7736917,
0.7277459,
0.681687,
0.6329853,
0.582352459,
0.5328522,
0.48483035,
0.436798245,
0.388586164,
0.3424556,
0.302069068,
0.267472,
0.237092659,
0.209047124,
0.184123,
0.163114548,
0.144511625,
0.126265839,
0.107269846,
0.08942619,
0.07420107,
0.06193066,
0.0517099164,
0.0435060449,
0.0383287631,
0.0352067538,
0.03245497,
0.0286534447,
0.0242379941,
0.0201460086,
0.016266821,
0.0121985339,
0.008013846,
0.00560544431,
0.00502379332,
0.004533774,
0.004487538,
0.00551742641,
0.007546712,
0.009179788,
0.009129186,
0.007475236,
0.005305866,
0.004060863,
0.00462530646,
0.00631512143,
0.00748074846,
0.007632819,
0.006844715,
0.00562061928,
0.005166012,
0.006103046,
0.00768285431,
0.009006567,
0.009526576,
0.009514096,
0.009059127,
0.008065625,
0.006526997,
0.00434135273,
0.00191119267,
0.00254829624,
0.006861757,
0.0108742379,
0.0131905386,
0.013858974,
0.0132871456,
0.012235119,
0.01142512,
0.01094334,
0.0107232835,
0.0107062105,
0.010995524,
0.0112270387,
0.0102753676,
0.00612402242,
0.0010008571,
0.00318561238,
0.009038351,
0.0119382814,
0.0132263815,
0.013723935,
0.0133564435,
0.0129926438,
0.0127558094,
0.011888911,
0.009955382,
0.00670363754,
0.00246145763,
0.000897339836,
0.0037357898,
0.006457583,
0.007566943,
0.007532189,
0.006015837
],
"Processed": false}
]}');
--This is the query to get all first level elements
SELECT ID
,A.*
FROM #mockupTable
CROSS APPLY OPENJSON(YourJson) A
WHERE ID=1;
--But there is the WITH-clause, which allows you to transform this list of columns to a single result row with typed columns:
SELECT ID
,A.*
FROM #mockupTable
CROSS APPLY OPENJSON(YourJson)
WITH
(
DateTime DATETIME N'$.DateTime'
,Side NVARCHAR(50) N'$.Side'
--add all variables of the first level
,Membrane INT N'$.Membrane'
) A
WHERE ID=1;
--With this we grab into the values of current:
SELECT ID
,A.*
,C.*
FROM #mockupTable
CROSS APPLY OPENJSON(YourJson)
WITH
(
DateTime DATETIME N'$.DateTime'
,Side NVARCHAR(50) N'$.Side'
--add all variables of the first level
,Membrane INT N'$.Membrane'
) A
CROSS APPLY OPENJSON(YourJson,'$.Current') C
WHERE ID=1;
--And the next query allows as to get the first-level-elements of the two objects within Measurement:
SELECT ID
,A.*
,M.*
FROM #mockupTable
CROSS APPLY OPENJSON(YourJson)
WITH
(
DateTime DATETIME N'$.DateTime'
,Side NVARCHAR(50) N'$.Side'
--add all variables of the first level
,Membrane INT N'$.Membrane'
) A
CROSS APPLY OPENJSON(YourJson,'$.Measurements')
WITH
(
FPOS INT N'$.FPOS'
,Orient VARCHAR(10) N'$.Orient'
--Add more
) M
WHERE ID=1;
--And this last query will return the two Measurements with all values in SDS. (Look at the AS JSON within the WITH-clause!):
SELECT ID
,A.*
,M.*
,V.*
FROM #mockupTable
CROSS APPLY OPENJSON(YourJson)
WITH
(
DateTime DATETIME N'$.DateTime'
,Side NVARCHAR(50) N'$.Side'
--add all variables of the first level
,Membrane INT N'$.Membrane'
) A
CROSS APPLY OPENJSON(YourJson,'$.Measurements')
WITH
(
FPOS INT N'$.FPOS'
,Orient NVARCHAR(10) N'$.Orient'
--Add more
,[SDS] NVARCHAR(MAX) AS JSON --allows to return the JSON reflecting the array
) M
CROSS APPLY OPENJSON(M.SDS) V
WHERE ID=1;
Now you know how to fetch everything. What you are going to do with this is up to you...