Reputation: 69
Firstly i obatin data from Excel and convert them into DataTable
in C# project.
Secondly i parse this DataTable
into JSON string and send it to database as a stored procedure parameter.
I want to perform the merge operation on some table with values from this JSON string parameter. Values from this parameter can be represented as such table:
DECLARE @JsonData NVARCHAR(MAX);
SET @JsonData = N'[
{"id": 1, "lval": "-10;15", "hval": "-20;45", "unit": "kg;m"}
]';
DECLARE @ExampleTable TABLE (EQ BIGINT, L_VALUE NVARCHAR(100), H_VALUE NVARCHAR(100), UNIT NVARCHAR (30))
INSERT INTO @ExampleTable
SELECT *
FROM OPENJSON(@JsonData) WITH (
[EQ] BIGINT 'strict $.id',
[L_VALUE] NVARCHAR(100) '$.lval',
[H_VALUE] NVARCHAR(100) '$.hval',
[UNIT] NVARCHAR(20) '$.unit')
SELECT * FROM @ExampleTable
EQ (ID) | L_VALUE (nvarchar(100)) | H_VALUE (nvarchar(100)) | UNIT(nvarchar(30)) |
---|---|---|---|
1 | -10;15 | -20;45 | kg;m |
The first value (from either L_VALUE or H_VALUE) before the semicolon stands for the first unit from the UNIT column, second stands for second unit etc... There can be more pairs of values and units or there can be simply one value one unit so in example:
EQ (ID) | L_VALUE (nvarchar(100)) | H_VALUE (nvarchar(100)) | UNIT(nvarchar(30)) |
---|---|---|---|
1 | 3;21;-19 | 2;11;-5 | kg;cm;ml |
or
EQ (ID) | L_VALUE (nvarchar(100)) | H_VALUE (nvarchar(100)) | UNIT(nvarchar(30)) |
---|---|---|---|
1 | 10 | -2 | cm |
I would like to obtain the result in the table form as follows:
EQ (ID FK) | L_VALUE (float) | H_VALUE (float)) | UNIT (nvarchar(30)) |
---|---|---|---|
1 | -10 | -20 | kg |
1 | 15 | 45 | m |
Upvotes: 0
Views: 446
Reputation: 29943
You may try to transform the values in the L_VALUE
, H_VALUE
and UNIT
columns as JSON (-10;25
into ["-10", "-25"]
) and parse the values with additional OPENJSON()
call. The result from the second OPENJSON()
is a table with columns key
, value
and type
and in case of an array, the key
column contains the index of each item in the JSON array, so you need an appropriate JOIN
s:
Table and JSON:
DECLARE @JsonData NVARCHAR(MAX);
SET @JsonData = N'[
{"id": 1, "lval": "-10;15", "hval": "-20;45", "unit": "kg;m"},
{"id": 2, "lval": "-10;15;13", "hval": "-20;45;55", "unit": "kg;m;cm"},
{"id": 3, "lval": "-10", "hval": "-20", "unit": "kg"}
]';
DECLARE @ExampleTable TABLE (
EQ BIGINT,
L_VALUE NVARCHAR(100),
H_VALUE NVARCHAR(100),
UNIT NVARCHAR (30)
)
Statement:
INSERT INTO @ExampleTable
SELECT j.[EQ], a.[L_VALUE], a.[H_VALUE], a.[UNIT]
FROM OPENJSON(@JsonData) WITH (
[EQ] BIGINT 'strict $.id',
[L_VALUE] NVARCHAR(100) '$.lval',
[H_VALUE] NVARCHAR(100) '$.hval',
[UNIT] NVARCHAR(20) '$.unit'
) j
CROSS APPLY (
SELECT l.[value], h.[value], u.[value]
FROM OPENJSON(CONCAT('["', REPLACE(j.L_VALUE, ';', '","'), '"]')) l
JOIN OPENJSON(CONCAT('["', REPLACE(j.H_VALUE, ';', '","'), '"]')) h ON l.[key] = h.[key]
JOIN OPENJSON(CONCAT('["', REPLACE(j.UNIT, ';', '","'), '"]')) u ON l.[key] = u.[key]
) a (L_VALUE, H_VALUE, UNIT)
Result:
EQ L_VALUE H_VALUE UNIT
----------------------
1 -10 -20 kg
1 15 45 m
2 -10 -20 kg
2 15 45 m
2 13 55 cm
3 -10 -20 kg
Upvotes: 3
Reputation: 95544
Assuming that there can only be 2 delimited values, and that there are always 2 delimited values, then you could do this:
SELECT JD.EQ,
V.L_VALUE,
V.H_VALUE,
V.UNIT
FROM OPENJSON(@JsonData)
WITH (EQ bigint '$.id',
lval varchar(100),
hval varchar(100),
unit nvarchar(20)) JD
CROSS APPLY(VALUES(LEFT(JD.lval,CHARINDEX(';',JD.lval)-1),LEFT(JD.hval,CHARINDEX(';',JD.hval)-1),LEFT(JD.unit,CHARINDEX(';',JD.unit)-1)),
(STUFF(JD.lval,1,CHARINDEX(';',JD.lval),''),STUFF(JD.hval,1,CHARINDEX(';',JD.hval),''),STUFF(JD.unit,1,CHARINDEX(';',JD.unit),'')))V(L_VALUE,H_VALUE,UNIT)
I don't use STRING_SPLIT
as it does not return the ordinal position, which could result in incorrect values being matched.
Upvotes: 0