Transform JSON column to string - sql-server-2016

I have a script that selects data into an XML table with a single column and then converts that into a string:
(
SELECT N'DECLARE #' + REPLACE( COLUMN_NAME, ' ', '_' ) + #CrLf
FROM #TABLE
FOR XML PATH(''), TYPE
).value( '.', 'nvarchar(max)' ) + #CrLf +
I'm trying to do the same thing with JSON but I just can't seem to figure out the last part. I'm able to create a table with a single column but no matter what I try, I can't seem to get it to convert to a string:
(
SELECT ( N'DECLARE #' + REPLACE( COLUMN_NAME, ' ', '_' ) + #CrLf ) AS MyString
FROM #TABLE
FOR JSON PATH
)
Here is a testable sample (which includes the above):
DECLARE #CrLf nchar(2) = CHAR(13) + CHAR(10);
DECLARE #TABLE TABLE ( [COLUMN_NAME] sysname );
INSERT INTO #TABLE VALUES
( 'COL1' ),
( 'COL2' ),
( 'COL3' ),
( 'COL4' ),
( 'COL5' );
DECLARE #Script nvarchar(max) =
(
SELECT N'DECLARE #' + REPLACE( COLUMN_NAME, ' ', '_' ) + #CrLf
FROM #TABLE
FOR XML PATH(''), TYPE
).value( '.', 'nvarchar(max)' ) + #CrLf +
(
SELECT ( N'DECLARE #' + REPLACE( COLUMN_NAME, ' ', '_' ) + #CrLf ) AS MyString
FROM #TABLE
FOR JSON PATH
);
SELECT #Script;
It outputs the following:
XML Transform:
DECLARE #COL1
DECLARE #COL2
DECLARE #COL3
DECLARE #COL4
DECLARE #COL5
JSON Transform:
[{"MyString":"DECLARE #COL1\r\n"},{"MyString":"DECLARE #COL2\r\n"},{"MyString":"DECLARE #COL3\r\n"},{"MyString":"DECLARE #COL4\r\n"},{"MyString":"DECLARE #COL5\r\n"}]
So in closing, I'm trying to get the JSON Transform to look the same as the XML Transform does.
Much appreciated.

This should do it
DECLARE #TABLE TABLE ( [COLUMN_NAME] sysname );
INSERT INTO #TABLE VALUES
( 'COL1' ),
( 'COL2' ),
( 'COL3' ),
( 'COL4' ),
( 'COL5' );
DECLARE #json NVARCHAR(MAX) =
(
SELECT N'DECLARE #' + REPLACE( COLUMN_NAME, ' ', '_' ) AS MyString
FROM #TABLE
FOR JSON PATH
)
SELECT JSON_VALUE(value,'$.MyString') AS 'JSON Transform'
FROM OPENJSON(#json,'$')
Results
+--------------+
|JSON Transform|
+--------------+
| DECLARE #COL1|
| DECLARE #COL2|
| DECLARE #COL3|
| DECLARE #COL4|
| DECLARE #COL5|
+--------------+
This link you help you understand the OPENJSON and JSON_VALUE functions, JSON Path Expressions

Related

Data insert into table dynamically

Example query which I used
Declare #DataColumn table (id int not null primary key identity(1,1), ColumnName Nvarchar(250),DataValue Nvarchar(250))
insert into #DataColumn
select DataColumnName, DataValue
from CustomObjectMappingTable obm
join #price_tmp temp on obm.ObjectFieldName = temp.FieldName
where temp.DataValue <> ''
select * from #DataColumn
Result is :
id ColumnName DataValue
-------------------------
1 Column_1 Umar Mehmood
2 Column_2 27
3 Column_3 21-nov-1992
4 Column_4 Male
5 Column_5 Gujar Khan District RWP
I have data into temp table and I need to insert into physical table using temp table. I want to use from temptable first columndata as " ColumnName" and second column data as "Data" how can I do this any one help me please?
Query for inserting
insert into CustomData (#DataColumn.ColumnName)
select *
from
(select DataValue, ColumnName
from #DataColumn) d
pivot
(max(DataValue)
for ColumnName in (ColumnName)
) piv;
Need it dynamically
Try the following:
DECLARE #DataColumn table ( id int, ColumnName varchar(50), DataValue varchar(50) );
INSERT INTO #DataColumn VALUES
( 1, 'Column_1', 'Umar Mehmood' ),
( 2, 'Column_2', '27' ),
( 3, 'Column_3', '21-nov-1992' ),
( 4, 'Column_4', 'Male' ),
( 5, 'Column_5', 'Gujar Khan District RWP' );
DECLARE #insert_columns varchar(MAX) = (
SELECT STUFF(
( SELECT ',[' + ColumnName + ']' FROM #DataColumn ORDER BY id FOR XML PATH( '' ) ),
1,
1,
''
)
);
DECLARE #insert_values varchar(MAX) = STUFF ( (
SELECT ',(' + STUFF(
( SELECT ',''' + DataValue + '''' FROM #DataColumn ORDER BY id FOR XML PATH( '' ) ),
1,
1,
''
) + ')'
), 1, 1, '' );
DECLARE #tsql varchar(MAX) = 'INSERT INTO CustomData (' + #insert_columns + ') VALUES ' + #insert_values + ';';
--EXEC(#tsql); -- Uncomment this line to execute the dynamic SQL.
PRINT #tsql;
The printed dynamic SQL:
INSERT INTO CustomData ([Column_1],[Column_2],[Column_3],[Column_4],[Column_5]) VALUES ('Umar Mehmood','27','21-nov-1992','Male','Gujar Khan District RWP');
We can do it using pivot table for dynamically
DECLARE #cols NVARCHAR(MAX), #query NVARCHAR(MAX) , #DataValues NVARCHAR(max);
SET #cols = STUFF( (SELECT DISTINCT ','+QUOTENAME(ColumnName) FROM ##DataColumn c FOR XML PATH(''), TYPE ).value('.', 'nvarchar(max)'), 1, 1, '');
SET #query = 'SELECT * from ( select [ColumnName],[DataValue] from ##DataColumn
) as sourcetable pivot (max(DataValue) for[ColumnName] in ('+#cols+')) p order by 1 ';
Insert into customdata ( [Column_1],[Column_2],[Column_3],[Column_4],[Column_5])
SELECT * from ( select [ColumnName],[DataValue] from #DataColumn ) as sourcetable
pivot (max(DataValue) for[ColumnName] in ([Column_1],[Column_2],[Column_3],[Column_4],[Column_5])) p order by 1

Create one row pivot select using column_names

I want make one row select into pivot select which uses column names from db.
EDIT:
SELECT *
FROM COR.PARAMETER_GROUP AS t WHERE GROUP_CODE = '555'
UNPIVOT
(
COLUMN_NAME
FOR VALUE IN(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PARAMETER_GROUP' AND TABLE_SCHEMA='COR' ORDER BY ORDINAL_POSITION ASC)
) AS u
--
COLUMN1 COLUMN2 COLUMN3 COLUMN4 COLUMN5
ROW 1 2 3 4 5
=
*COLUMN_NAME VALUE*
COLUMN1 1
COLUMN2 2
COLUMN3 3
COLUMN4 4
Basicaly i try this but i cant put column names in FOR
Are you looking for this:
CREATE TABLE #DataSource
(
[name] SYSNAME
,[pos] INT
);
INSERT INTO #DataSource ([name], [pos])
SELECT COLUMN_NAME
,ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [TABLE_NAME] = 'PARAMETER_GROUP'
AND TABLE_SCHEMA='COR';
DECLARE #DynammicTSQLStatement NVARCHAR(MAX)
,#DynamicPIVOTColumns NVARCHAR(MAX);
SET #DynamicPIVOTColumns = STUFF
(
(
SELECT ',' + QUOTENAME([name])
FROM #DataSource
ORDER BY [pos]
FOR XML PATH('') ,TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET #DynammicTSQLStatement = N'
SELECT *
FROM #DataSource
PIVOT
(
MAX([pos]) FOR [name] IN (' + #DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql #DynammicTSQLStatement;
DROP TABLE #DataSource;
I am using dynamic T-SQL statement to build the PIVOT statement in order to make it work for each table/view.
Here's your dynamic query.
declare #cols nvarchar(max);
declare #sql nvarchar(1000);
select #cols =
STUFF((select N',' + QUOTENAME([COLUMN_NAME])
from (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PARAMETER_GROUP' AND TABLE_SCHEMA='COR') t1
FOR XML PATH('')
), 1, 1, '') + N'';
set #sql = N'select ' + #cols + N' from
(
SELECT cast(ordinal_position as varchar(50)) as ordinal_position
, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''PARAMETER_GROUP'' AND TABLE_SCHEMA=''COR''
) t1
pivot
(
max(t1.ordinal_position)
for t1.column_name in (' + #cols + N')
) p '
exec sp_executesql #sql;

Select not null columns as a comma separated string from dynamic sql

I am trying to do my best to avoid using cursors. There is a comma separated list of columns in nvarchar variable that looks like this:
#columnList = 'col1,col2,col5'
There is a table with lots of varchar columns:
myTable: [col1],[col2],[col3],[col4],[col5],[col6],[col7]
This is how I select data using a dynamic sql:
exec ('select ' + #columnList + ' from myTable')
This query returns the following results:
[col1], [col2] , [col5]
null , "txt1" , null
"txt2", null , null
null , "txt3" , "txt4"
This is what I need to get:
#resultList = "txt1,txt2,txt3,txt4"
How do I select a comma separated string containing not-null values only? I know how to convert a table to comma separated string, so getting something like:
[column]
"txt1"
"txt2"
"txt3"
"txt4"
Is also fine. Any suggestions? Feel free to suggest a basic approach, I don't expect you to write the actual code for me.
You can use a solution like the following, using just a REPLACE to create the SQL query:
DECLARE #columnList VARCHAR(100)
SET #columnList = 'col1,col2,col5'
SET #columnList = REPLACE(#columnList, ',', ' AS colName FROM myTable UNION ALL SELECT ');
EXEC('SELECT * FROM (SELECT ' + #columnList + ' AS colName FROM myTable)t WHERE NOT t.colName IS NULL');
You can also use a solution using UNPIVOT:
DECLARE #columnList VARCHAR(100);
SET #columnList = 'col1,col2,col5';
EXEC('SELECT colName FROM (SELECT ' + #columnList + ' FROM myTable) t1 UNPIVOT (colName FOR columnNames IN (' + #columnList + ')) AS t2');
demo on dbfiddle.uk
Since you mention you already know how to aggregate into comma-seperated, here's how to unpivot your table with cross apply:
select unpivoted.*
from myTable
cross apply
( values
('col1',col2)
,('col2',col2)
,('col3',col3) -- etc
)unpivoted(colname,colval)
This would work for SQL Server 2017, on earlier version STRING_AGG usage should be replaced with XML-based solution.
You could first concatenate your results into a single line and then use STRING_AGG to aggregate them into a single string:
;with t as
(
SELECT * FROM (VALUES
(null , 'txt1' , null),
('txt2', null , null),
(null , 'txt3' , 'txt4')) x(col1, col2, col5)
)
SELECT STRING_AGG(STUFF(CONCAT(',' + col1, ',' + col2, ',' + col5), 1, 1, ''), ',')
FROM t
CTE is just for showcasing, you can simply do it in your dynamic query:
DECLARE #columnList NVARCHAR(MAX) = 'col1,col2,col5'
DECLARE #query NVARCHAR(MAX) = ''
SELECT #query = 'SELECT STRING_AGG(STUFF(CONCAT('','' + ' + REPLACE(#columnList, ',', ', '','' + ') + '), 1, 1, ''''), '','') from mytable'
EXEC sp_executesql #query
Working example on dbfiddle

Pivot multiple columns with a column value repeats for each new column

I need your help to build an sql query/sp for the following output.
My table is with the following data:
I would like to generate output like the following:
Kindly note, here, FieldName are not just four as in the table, it varies.
Find below the data:
CREATE TABLE #Results
(
FieldName nvarchar(50),
FieldValue nvarchar(50),
RecordStaus int
);
INSERT INTO #Results(FieldName,FieldValue,RecordStaus)
VALUES ('Coverage',NULL,1)
,('Premium',NULL,2)
,('F1',100,1)
,('F2',100,1)
,('Coverage',200,1)
,('Premium',10,1)
,('F1',50,1)
,('F2',NULL,3)
,('Coverage',300,1)
,('Premium',45,1)
,('F1',24,1)
,('F2',NULL,1)
,('Coverage',450,3)
,('Premium',12,3)
,('F1',50,1)
,('F2',NULL,1);
You can try this:
CREATE TABLE #Results
(
id int identity(1,1),
FieldName nvarchar(50),
FieldValue nvarchar(50),
RecordStaus int
);
INSERT INTO #Results(FieldName,FieldValue,RecordStaus)
VALUES ('Coverage',NULL,1)
,('Premium',NULL,2)
,('F1',100,1)
,('F2',100,1)
,('Coverage',200,1)
,('Premium',10,1)
,('F1',50,1)
,('F2',NULL,3)
,('Coverage',300,1)
,('Premium',45,1)
,('F1',24,1)
,('F2',NULL,1)
,('Coverage',450,3)
,('Premium',12,3)
,('F1',50,1)
,('F2',NULL,1);
DECLARE #DynamicTSQLStatement NVARCHAR(MAX)
,#Columns NVARCHAR(MAX);
SELECT #Columns = STUFF
(
(
SELECT *
FROM
(
SELECT DISTINCT ',[' + CAST([FieldName] AS NVARCHAR(50)) + ']'
FROM #Results
UNION
SELECT DISTINCT ',[' + CAST([FieldName] + '_RecordStaus' AS NVARCHAR(50)) + ']'
FROM #Results
) DS ([FieldName])
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1
,1
,''
);
SET #DynamicTSQLStatement = N'
SELECT *
FROM
(
SELECT [FieldName]
+ CASE WHEN [Column] = ''RecordStaus'' THEN ''_RecordStaus'' ELSE '''' END AS [FieldName]
,[rowID]
,[Value]
FROM
(
SELECT [FieldName]
,[FieldValue]
,CAST([RecordStaus] AS NVARCHAR(50))
,ROW_NUMBER() OVER (PARTITION BY [FieldName] ORDER BY [id])
FROM #Results
) DS ([FieldName], [FieldValue], [RecordStaus], [rowID])
UNPIVOT
(
[Value] FOR [Column] IN ([FieldValue], [RecordStaus])
) UNPVT
) ReadyForPivot
PIVOT
(
MAX([Value]) FOR [FieldName] IN (' + #Columns +')
) PVT;
';
EXEC sp_executesql #DynamicTSQLStatement;
DROP TABLE #Results;
Few notes:
I have added id column in order to know the value for which row / in your real case you can use ordering by something else or SELECT 1 in the ROW_NUMBER function; you need such way in order to be sure the results are deterministic;
I am using dynamic SQL in order to make the query work for various values of FildName column - if you need specific order of the columns, you can do this using ORDER BY clause in the FOR XML clause. For example:
SELECT #Columns = STUFF
(
(
SELECT *
FROM
(
SELECT DISTINCT ',[' + CAST([FieldName] AS NVARCHAR(50)) + ']'
FROM #Results
UNION
SELECT DISTINCT ',[' + CAST([FieldName] + '_RecordStaus' AS NVARCHAR(50)) + ']'
FROM #Results
) DS ([FieldName])
ORDER BY [FieldName] DESC -- you can order the columns as you like
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1
,1
,''
);
Then add the #columns variable value in the dynamic SQL:
SET #DynamicTSQLStatement = N'
SELECT' + #columns + ' ...

Inserting Different Value IN a Table

Well I'm Creating a Table Based on Result Set Of Databases On Server which contain Multiple Databases.
My table will Create a list of column which contain Database_Name
FOR EG:
DECLARE #strt INT,#End INT,#Database NVARCHAR(20), #ColumnDeclaration VARCHAR(2000),#SqlSelect NVARCHAR(MAX),#column_Name NVARCHAR(255)
SELECT * INTO #T FROM SYS.DATABASES
ORDER BY NAME
SELECT #ColumnDeclaration=STUFF(( SELECT ', ' + Name + ' NVARCHAR(255)'
FROM #T
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(max)'), 1, 1, '')
SET #SqlSelect=' CREATE TABLE Temp_Comp (' + #ColumnDeclaration + ');'
PRINT #SqlSelect
EXEC (#SqlSelect)
SELECT * FROM Temp_Comp
I wan't Insert the Data INTO Temp_Comp Table a specific Value from
the database whose Name will be in Temp_comp Table
Not sure what are you trying to achieve, but I assume that you want something like:
DECLARE #strt INT,#End INT,#Database NVARCHAR(20), #ColumnDeclaration NVARCHAR(MAX),#SqlSelect NVARCHAR(MAX),#column_Name NVARCHAR(255)
SELECT * INTO #T
FROM SYS.DATABASES
ORDER BY NAME;
SELECT #ColumnDeclaration=STUFF(( SELECT ', ' + QUOTENAME(Name) + ' NVARCHAR(255)'
FROM #T
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(max)'), 1, 1, '');
SET #SqlSelect=' CREATE TABLE Temp_Comp (col_desc NVARCHAR(200), ' + #ColumnDeclaration + ');';
SELECT #SqlSelect;
EXEC (#SqlSelect);
SET #SQLSelect = ' INSERT INTO Temp_Comp(col_desc, ' + REPLACE(#ColumnDeclaration, 'NVARCHAR(255)', '') + ')' +
' SELECT col,'+ REPLACE(#ColumnDeclaration, 'NVARCHAR(255)', '') +' FROM (' +
' SELECT name, sub.* FROM sys.databases' +
' OUTER APPLY (SELECT ''database_id'', CAST(database_id AS NVARCHAR(MAX)) UNION ALL SELECT ''compatibility_level'', CAST(compatibility_level AS NVARCHAR(MAX)) ) sub(col, val)) src' +
' PIVOT (MAX(val) FOR name IN ('+ REPLACE(#ColumnDeclaration, 'NVARCHAR(255)', '') +') ) piv';
SELECT #SQLSelect;
EXEC (#SQLSelect);
DBFiddle
Result:
In order to INSERT you could use dynamic PIVOT. To add more values just extend OUTER APPLY part.
Keep in mind that you've defined columns as ' NVARCHAR(255)' so you may need to convert values before insert.