TSQL, how to retrieve data from multiple JSON rows from a database - sql

I have in my table rows with JSON same as a example:
json_data
[{"d":"2021-05-05T12:16:18.9175335","l":"temp12#cor.net","a":"test1","c":"Kom1"}]
[{"d":"2021-05-05T12:16:37.7258608","l":"temp12#cor.net","a":"test2","c":"Kom2"}]
[{"d":"2021-05-05T12:17:30.2390585","l":"temp12#cor.net","a":"test3","c":"Kom3"}]
I want to get data in table format. When is 1 row i don't have problem using:
DECLARE #JSONINPUT NVARCHAR(max)
SET #JSONINPUT = (select top 1 cast(json_data as varchar(max)) from mytable )
IF (ISJSON(#JSONINPUT) = 1)
BEGIN
SELECT * from OPENJSON(#JSONINPUT )
WITH (
[Kom] nvarchar(max) '$.c',
[Date] DATETIME2 '$.d',
[User] nvarchar(150) '$.a'
);
END
and i get:
Com
Date
User
Kom1
2021-05-05 12:16:18.9175335
test1
But I don't know how to get data from all rows.

Use CROSS APPLY with OPENJSON
SELECT j.Kom, j.[Date], j.[User]
FROM mytable
CROSS APPLY OPENJSON(json_data)
WITH (
[Kom] nvarchar(max) '$.c',
[Date] DATETIME2 '$.d',
[User] nvarchar(150) '$.a'
) AS j;

The syntax, as I mentioned, is no different:
SELECT OJ.Kom,
OJ.[Date],
OJ.[User]
FROM dbo.YourTable YT
CROSS APPLY OPENJSON(YT.JSONColumn)
WITH ([Kom] nvarchar(max) '$.c',
[Date] DATETIME2 '$.d',
[User] nvarchar(150) '$.a') OJ;

Related

Convert SQL Json iteration into bulk process

I have a data table with JSON documents in one column right now I iterate through each row to pivot out a(n) JSON array and flatten it out into another table. Is there a way to do this in a bulk action instead of an iteration process?
DECLARE #json varchar(max)
SET #json = (SELECT document
FROM dbo.MYJsonTable WITH (NOLOCK)
WHERE rawid = 4170159) -- unique identity value
SELECT
b.objectid,
b.staffRole,
b.statusName,
b.gwySync,
b.createdate,
b.rawid,
b.loaddate,
ROW_NUMBER() OVER (PARTITION BY objectid ORDER BY createdate) as row_num
FROM
(SELECT
JSON_Value(RePlace(#json,'$','') ,'$._id.oid') [objectid],
staffRole,
[statusName],
[gwySync],
DATEADD (hour, -6, DATEADD(MS, TRY_CONVERT(BIGINT, LEFT(Replace([$numberLong], '$', ''),10)), '1970-01-01 00:00:00')) [createdate],
4170159 [rawid],
GETDATE() [loaddate]
FROM
OPENJSON(#json, '$.patientJourneySteps')
WITH
(statusLog NVARCHAR(max) as JSON,
staffRole nvarchar(50) '$.staffRole') patientJourneySteps
OUTER APPLY
OPENJSON(patientJourneySteps.statusLog, '$')
WITH
(statusName NVARCHAR(15) '$.statusName',
gwySync nvarchar(20) '$.gwySync',
createdDate NVARCHAR(max) AS JSON) logs
OUTER APPLY
OPENJSON(logs.createdDate,'$')
WITH
([$date] NVARCHAR(max) AS JSON) DateJson
OUTER APPLY
OPENJSON(DateJson.[$date],'$')
WITH
([$numberLong] NVARCHAR(30))
) b

Compare 2 columns value in a table and show the matching values in a new column . column values are comma seperated

Here I want to compare the comma-separated values from the column roles and userroles, then show the matching values in another column.
I found an example compare comma separated values in sql and used the cursor to iterate rows one by one. it's working for me. but I feel there should be a better way to do it.
Any help is much appreciated.
Create table #temp4
(
user_id int,
permission_id int,
roles varchar(max),
userroles varchar(max),
matchingrolesinthisrow varchar(max))
Insert Into #temp4 values
( 1, -12010, '2341,8760,3546', '1000,1001,1002,1003', null),
( 1, -334, '1002,1001,3467', '2341,1002,3467', null),
( 2, -12349, '9876,9982,6548', '1001,1002,2341', null)
below is the result table I am looking for.
user_id
permission_id
roles
userroles
matchingrolesinthisrow
1
-12010
2341,8760,3546
1000,1001,1002,1003
1
-334
1002,1001,3467
2341,1002,3467
1002,3467
2
-12349
9876,9982,6548
1001,1002,2341
My attempt so far and it's working. please guide me to do this in a better way.
DECLARE #user_id INT
DECLARE #permission_id INT
DECLARE #roles VARCHAR(MAX)
DECLARE #userroles VARCHAR(MAX)
DECLARE #matchingrolesinthisrow VARCHAR(MAX)
declare cur CURSOR LOCAL for
select user_id, permission_id, roles, userroles, matchingrolesinthisrow from #temp4 order by 1
open cur
fetch next from cur into #user_id, #permission_id, #roles, #userroles, #matchingrolesinthisrow
while ##FETCH_STATUS = 0 BEGIN
print (#roles)
print(#userroles)
--execute on each row
UPDATE #temp4
SET matchingrolesinthisrow = T1.[Item]
FROM [developers].[Split](#roles, ',') AS T1
INNER JOIN [developers].[Split](#userroles, ',') AS T2 on T1.[Item] = T2.[Item]
Where roles = #roles and userroles = #userroles and permission_id = #permission_id and user_id = #user_id
fetch next from cur into #user_id, #permission_id, #roles, #userroles, #matchingrolesinthisrow
END
close cur
deallocate cur
--Split function
CREATE FUNCTION [developers].[Split]
(
#s VARCHAR(max),
#split CHAR(1)
)
RETURNS #temptable TABLE ([Item] VARCHAR(MAX))
AS
BEGIN
DECLARE #x XML
SELECT #x = CONVERT(xml,'<root><s>' + REPLACE(#s,#split,'</s><s>') + '</s></root>');
INSERT INTO #temptable
SELECT [Value] = T.c.value('.','varchar(20)')
FROM #X.nodes('/root/s') T(c);
RETURN
END;
Ideally, you should store each inidividual piece of information in separate row, so you should have two separate tables roles and userroles which are foreign-keyed on this one.
Be that as it may, this does not need cursors. You can use STRING_SPLIT and STRING_AGG to get the result you want very easily:
SELECT
t4.user_id,
t4.permission_id,
t4.roles,
t4.userroles,
matchingrolesinthisrow = (
SELECT STRING_AGG(r.value, ',')
FROM STRING_SPLIT(t4.roles, ',') r
JOIN STRING_SPLIT(t4.userroles, ',') ur ON ur.value = r.value
)
FROM #temp4 t4;
SQL Fiddle
If you are on an early version of SQL Server, you will have to use custom Table Valued Functions to do this.
Modified the shared answer to work in the lower version of SQL Server.
SELECT
t4.user_id,
t4.permission_id,
t4.roles,
t4.userroles,
STUFF((SELECT N',' + CONVERT(nvarchar(2000),r.value)
FROM STRING_SPLIT(t4.roles, ',') r
INNER JOIN STRING_SPLIT(t4.userroles, ',') ur ON ur.value = r.value
FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') as matchingrolesinthisrow
FROM #temp4 t4;

Data Truncated in SQL Server when assign json to variable

I want to generate JSON using T-SQL and stored it in a variable. When I assign the JSON to a NVARCHAR(MAX) the data is being truncated, But it is not being truncated if I directly use the select statement.
DECLARE #DateOne DATETIME, #DateTwo DATETIME,#DrillThroughData NVARCHAR(MAX)
SELECT #DateOne = '2016-01-01',#DateTwo = '2017-07-31'
CREATE TABLE #DrillThroughData
(
[Date] DATE
,TotalAmountIncome DECIMAL(18,4)
,TotalAmountRefunded DECIMAL(18,4)
,ProductCostIncome DECIMAL(18,4)
,ProductCostRefunded DECIMAL(18,4)
)
INSERT INTO #DrillThroughData
VALUES('2017-07-13',839.2000,-241.4000,0.0000,0.0000)
;WITH CTE AS
(
SELECT 1 SNo,CAST(CONVERT(NVARCHAR(6),#DateOne,112)+'01' AS DATE) AS StartDate
UNION ALL
SELECT SNo+1 SNo,DATEADD(DAY,1,StartDate ) StartDate
FROM CTE WHERE DATEADD(Day,1,StartDate ) <= #DateTwo
)
SELECT StartDate [Date],SNo
INTO #AllDays
FROM CTE
OPTION(MAXRECURSION 0)
-- Data not truncated here.
SELECT ad.[Date]
,FORMAT(ad.[Date],'yyyy-MMM') [Month]
,ISNULL(d.TotalAmountIncome,0) TotalAmountIncome
,ISNULL(d.TotalAmountRefunded,0) TotalAmountRefunded
,ISNULL(d.ProductCostIncome,0) ProductCostIncome
,ISNULL(d.ProductCostRefunded,0) ProductCostRefunded
FROM #DrillThroughData d
RIGHT JOIN #AllDays ad
ON d.[Date] = ad.Date
ORDER BY SNo
FOR JSON AUTO
SET #DrillThroughData = (SELECT ad.[Date]
,FORMAT(ad.[Date],'yyyy-MMM') [Month]
,ISNULL(d.TotalAmountIncome,0) TotalAmountIncome
,ISNULL(d.TotalAmountRefunded,0) TotalAmountRefunded
,ISNULL(d.ProductCostIncome,0) ProductCostIncome
,ISNULL(d.ProductCostRefunded,0) ProductCostRefunded
FROM #DrillThroughData d
RIGHT JOIN #AllDays ad
ON d.[Date] = ad.Date
ORDER BY SNo
FOR JSON AUTO)
-- Data is being Truncated even though the varaible is nvarchar(max)
SELECT #DrillThroughData
The actual length of the json when not truncated is 88441, but it is truncated at 13680.
Thanks in advance.

dynamic alias in sql server

I want query field with different alias in stored procedure
select COUNT(EmpCode) as CountEmp+#para
result shoud be
CountEmp1
45
CountEmp2
54
CountEmp1
76
Query loop in c# code:
select COUNT(EmpCode) where something = #something as CountEmp+#para
Approach without dynamic SQL:
--I create temp table for demonstration
DECLARE #some_table TABLE (
Something int,
EmpCode INT
)
INSERT INTO #some_table (Something, EmpCode)
VALUES (1, 10),(1, 22),(1, 12),(2, 12),(2, 30),(3, 65),(3, 15),(3, 11),(3, 5)
--Declare parameter we want to search
DECLARE #param int = 1
--Query
--In cte we select what we need based on parameter
;WITH cte AS (
SELECT 'CountEmp'+CAST(#param as nvarchar(10)) as SomeThing,
CAST(COUNT(EmpCode) as nvarchar(10)) as EmpCodeCount,
ROW_NUMBER() OVER (ORDER BY SomeThing ) as rn
FROM #some_table
WHERE SomeThing = #param
GROUP BY SomeThing
)
--And here comes UNION
SELECT SomeThing as Result
FROM (
SELECT SomeThing,rn
FROM cte
UNION ALL
SELECT EmpCodeCount ,rn
FROM cte
) as t
ORDER BY rn, SomeThing DESC
Output:
Result
------------------
CountEmp1
3
(2 row(s) affected)
Please try to make use of below code. Its working fine with SQL Server 2012.
IF OBJECT_ID ('temp..#Mytable') IS NOT NULL
CREATE TABLE #Mytable (ID INT IDENTITY (1,1),EmpCode INT)
DECLARE #max int ,#count int
SET #max =0;
DECLARE #str varchar(10)
INSERT #Mytable
(EmpCode)
VALUES
(10),
(45),
(35),
(63),
(56),
(65)
SET #count = (SELECT COUNT (ID) FROM #Mytable )
WHILE #count > #max
BEGIN
SET #max = #max+1
SET #str = CONVERT(varchar(10),#max)
EXEC('SELECT EmpCode AS Empcode'+#str+ ' FROM #Mytable WHERE ID = '+#str)
END

My query is not working as expected

My query is not working which is as follows:
CREATE TABLE #tempCal (
CategoryId BIGINT
,CategoryName NVARCHAR(max)
,ElementWeight MONEY
,MakingCharges MONEY
,GemstoneAttribute NVARCHAR(max)
,AlloyAttribute NVARCHAR(max)
,Rates MONEY
)
--insert into #tempCal(CategoryId,CategoryName,ElementWeight,MakingCharges,GemstoneAttribute,AlloyAttribute,Rates)
--values
DECLARE #iterator BIGINT = (
SELECT max(MstJewelleryProduct.ID)
FROM MstJewelleryProduct
)
INSERT INTO #tempCal (
CategoryId
,CategoryName
,ElementWeight
,MakingCharges
,GemstoneAttribute
,AlloyAttribute
,Rates
)
VALUES (
(
SELECT MstJewelleryProduct.ElementWeight
,MstJewelleryProduct.Element_Price
,MstJewelleryProduct.MakingCharges
,MstJewelleryProduct.GemstoneAttribute
,MstJewelleryProduct.AlloyAttribute
,MstJewelleryCategory.ID
,MstJewelleryCategory.CategoryName
,MstRates.Rates
,MstJewelleryOffers.OfferAmount
FROM MstJewelleryProduct
INNER JOIN MstJewelleryCategory ON MstJewelleryProduct.CategoryID = MstJewelleryCategory.ID
LEFT JOIN MstRates ON MstJewelleryProduct.CategoryID = MstRates.CategoryId
LEFT JOIN MstJewelleryOffers ON MstJewelleryProduct.CategoryID = MstJewelleryOffers.ProductCategory
AND MstJewelleryOffers.IsActive = 1
WHERE MstJewelleryProduct.IsActive = 1
)
)
SELECT *
FROM #tempCal
DROP TABLE #tempCal
The syntax of the (Insert Into) is not correct. When you use (Select) you do not need to use (Values). Please refer to this link to check the right syntax.