Putting comma separated values into separate or different columns - sql

I have a table and values as shown here
create table #example(id int primary key identity, cols varchar(255))
insert into #example(cols) values('HI,HELLO,BYE,TC')
insert into #example(cols) values('WHAT,ARE,YOU,DOING,HERE')
I need the resultant output as shown in the picture
Note : There is no limit for values i.e dynamic

This is what you are expecting
Schema:
CREATE TABLE #EXAMPLE(ID INT PRIMARY KEY IDENTITY, COLS VARCHAR(255))
INSERT INTO #EXAMPLE(COLS) VALUES('HI,HELLO,BYE,TC')
INSERT INTO #EXAMPLE(COLS) VALUES('WHAT,ARE,YOU,DOING,HERE')
Do split those comma separated values into Rows and Apply pivot
SELECT * FROM (
SELECT id
, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT 1)) AS ID2
, SPLT.CLMS.value('.','VARCHAR(MAX)') AS LIST FROM (
select id
, CAST( '<M>'+REPLACE(cols,',','</M><M>')+'</M>' AS XML) AS XML_COL from #example E
)E
CROSS APPLY E.XML_COL.nodes('/M') AS SPLT(CLMS)
)A
PIVOT
(
MAX(LIST) FOR ID2 IN ([1],[2],[3],[4],[5])
)PV
You will get result as
+----+------+-------+-----+-------+------+
| id | 1 | 2 | 3 | 4 | 5 |
+----+------+-------+-----+-------+------+
| 1 | HI | HELLO | BYE | TC | NULL |
| 2 | WHAT | ARE | YOU | DOING | HERE |
+----+------+-------+-----+-------+------+
Edit:
And now you need to go for dynamic pivot,since There is no limit for values.
DECLARE #COLS VARCHAR(MAX)='', #QRY VARCHAR(MAX)='';
SELECT #COLS =#COLS+'['+CAST( ID2 AS VARCHAR(10))+'],' FROM (
SELECT DISTINCT ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT 1)) AS ID2 FROM (
select id, CAST( '<M>'+REPLACE(cols,',','</M><M>')+'</M>' AS XML) AS XML_COL from #example E
)E
CROSS APPLY E.XML_COL.nodes('/M') AS SPLT(CLMS)
)A
SELECT #COLS = LEFT(#COLS,LEN(#COLS)-1)
SELECT #QRY =
'
SELECT * FROM (
SELECT id
, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT 1)) AS ID2
, SPLT.CLMS.value(''.'',''VARCHAR(MAX)'') AS LIST FROM (
select id, CAST( ''<M>''+REPLACE(cols,'','',''</M><M>'')+''</M>'' AS XML) AS XML_COL from #example E
)E
CROSS APPLY E.XML_COL.nodes(''/M'') AS SPLT(CLMS)
)A
PIVOT
(
MAX(LIST) FOR ID2 IN ('+#COLS+ ')
)PV'
EXEC( #QRY)

Dynamic version base on split string then pivot table
Schema:
create table #example(id int primary key identity, cols varchar(255))
insert into #example(cols) values('HI,HELLO,BYE,TC')
insert into #example(cols) values('WHAT,ARE,YOU,DOING,HERE')
Calculate columns pivot
-- Calculate dynamic columns
;WITH temps AS
(
SELECT sd.* ,CAST('<x>' + replace(sd.cols, ',', '</x><x>') + '</x>' as xml) AS xmlText
FROM #example sd
),
temps1 AS
(
SELECT t.Id, t.cols, v.x.value('.','varchar(50)') AS Value
FROM temps t
CROSS APPLY
t.xmlText.nodes('/x') AS v(x)
)
SELECT #ColumnPivot = STUFF((SELECT DISTINCT CONCAT(',COL',row_number() OVER(PARTITION BY t.id ORDER BY t.Value)) FROM temps1 t FOR XML PATH('')), 1,1,'')
PRINT #ColumnPivot
Then PIVOT table
DECLARE #query nvarchar(max) =
CONCAT(N';WITH temps AS
(
SELECT sd.* ,CAST(''<x>'' + replace(sd.cols, '','', ''</x><x>'') + ''</x>'' as xml) AS xmlText
FROM #example sd
),
temps1 AS
(
SELECT t.Id, t.cols, v.x.value(''.'' , ''varchar(50)'') AS Value
FROM temps t
CROSS APPLY
t.xmlText.nodes(''/x'') AS v(x)
),
temps2 AS
(
SELECT t.* , CONCAT(''COL'',row_number() OVER(PARTITION BY t.id ORDER BY (select 1))) AS ColGroup
FROM temps1 t
)',
N'SELECT Id, cols, ' , #ColumnPiVot,
' FROM
(
select * from temps2
) AS src
PIVOT
(MAX(Value) FOR ColGroup IN (',#ColumnPiVot,')) AS pvt')
PRINT #query
exec sp_executesql #query
DROP TABLE #example
Demo link: Rextester

DECLARE #COLS AS NVARCHAR(MAX),
#QUERY AS NVARCHAR(MAX);
SET #COLS = STUFF((SELECT DISTINCT ',' + QUOTENAME(C.RN)
FROM (SELECT ID,TOKEN,COLS
,ROW_NUMBER() OVER (
PARTITION BY ID ORDER BY (
SELECT NULL
)
) AS RN
FROM #EXAMPLE
CROSS APPLY (
SELECT *
FROM UDF_SPLITSTRING(COLS, ',')
) A) C
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #QUERY = 'SELECT ID,cols, ' + #COLS + ' FROM
(
SELECT ID,TOKEN,cols
,ROW_NUMBER() OVER (
PARTITION BY ID ORDER BY (
SELECT NULL
)
) AS RN
FROM #EXAMPLE
CROSS APPLY (
SELECT *
FROM UDF_SPLITSTRING(COLS, '','')
) A
) X
PIVOT
(
MAX(TOKEN)
FOR rn IN (' + #COLS + ')
) P '
exec(#QUERY)
output
ID cols 1 2 3 4 5
1 HI,HELLO,BYE,TC HI HELLO BYE TC NULL
2 WHAT,ARE,YOU,DOING,HERE WHAT ARE YOU DOING HERE

Related

Multiple Rows into One Row multiple columns

We need to list all numbers as a flat data set, how can we do that?
Table Name: Telephone
ID TYPE NUMBER
==================================
123 MN 042153939
123 HN 2242116
123 MN 1234567890
123 HN 12345678
Create Table Telephone
(
ID Integer,
Type char(3),
Number Varchar(20)
);
insert into Telephone values
(123, 'MN', '042153939'),
(123, 'HN', '2242116'),
(123, 'MN', '1234567890'),
(123, 'HN', '12345678');
I want SQL to return data in this format
ID MN#1 Mn#2 HN#1 HN#2
================================================
123 042153939 1234567890 2242116 12345678
Dynamic approach
Init
DROP TABLE IF EXISTS #Telephone;
CREATE TABLE #Telephone(ID INT,Type CHAR(3),Number VARCHAR(20));
INSERT INTO #Telephone (ID,Type,Number) VALUES
(123, 'MN', '042153939'),
(123, 'HN', '2242116'),
(123, 'MN', '1234567890'),
(123, 'HN', '12345678');
The code
DECLARE #ColumnList NVARCHAR(MAX);
SELECT #ColumnList = STUFF((SELECT ',[' + RTRIM(t.[Type]) + '#'
+ CONVERT(NVARCHAR(255),ROW_NUMBER()OVER(PARTITION BY t.[Type] ORDER BY t.ID)) + ']'
FROM #Telephone t FOR XML PATH(''),TYPE).value('(./text())[1]','NVARCHAR(MAX)'),1,1,'')
;
DECLARE #sql NVARCHAR(MAX) = '';
SET #sql = N'
SELECT ID,' + #ColumnList + N'
FROM (
SELECT t.ID,t.Number, RTRIM(t.[Type]) + ''#'' + CONVERT(NVARCHAR(255),ROW_NUMBER()OVER(PARTITION BY t.[Type] ORDER BY t.ID)) AS [Type]
FROM #Telephone t
) a
PIVOT(MAX(a.Number) FOR a.Type IN (' + #ColumnList + N')) p
'
;
--PRINT #sql
IF #sql IS NOT NULL EXEC(#sql);
try pivoting like below :
SELECT first_column AS <first_column_alias>,
[pivot_value1], [pivot_value2], ... [pivot_value_n]
FROM
(<source_table>) AS <source_table_alias>
PIVOT
(
aggregate_function(<aggregate_column>)
FOR <pivot_column> IN ([pivot_value1], [pivot_value2], ... [pivot_value_n])
) AS <pivot_table_alias>;
We can try using a pivot query with the help of ROW_NUMBER():
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY TYPE DESC, NUMBER) rn
FROM Telephone
)
SELECT
ID,
MAX(CASE WHEN rn = 1 THEN NUMBER END) AS [MN#1],
MAX(CASE WHEN rn = 2 THEN NUMBER END) AS [MN#2],
MAX(CASE WHEN rn = 3 THEN NUMBER END) AS [HN#3],
MAX(CASE WHEN rn = 4 THEN NUMBER END) AS [HN#4]
FROM cte
GROUP BY ID;
You may try this. with row_number() and pivot.
For more info about pivot you may find this link PIVOT.
; with cte as (
select row_number() over (partition by type order by id ) as Slno, * from Telephone
)
, ct as (
select id, type + '#' + cast(slno as varchar(5)) as Type, values from cte
)
select * from (
select * from ct
) as d
pivot
( max(values) for type in ( [MN#1],[Mn#2],[HN#1],[HN#2] )
) as p

SQL Server 2016: Turn multiple lines into columns with the different iterations

I have a table that has many InsuranceNo's for unique MemberIDs. If there are more than one InsuranceNo, I want the InsuranceNo's to shift to a column, so in the end there is one line per MemberID, with all the iterations of that ID's InsuranceNo's as a Column.
MemberID InsuranceNo
--------------------------
123456 dser
124571 jklh
123456 abcd
I want it to look like this:
MemberID InsuranceNo1 InsuranceNo2
-----------------------------------------------------
123456 dser abcd
124571 jklh
Thank you!
Yet another option... Just change "YourTable" to your actual table name.
Example
Declare #SQL varchar(max) = '
Select *
From (
Select MemberID
,Item = concat(''InsuranceNo'',row_number() over (Partition By MemberID Order By (Select NULL)))
,Value = InsuranceNo
From YourTable
) A
Pivot (max([Value]) For [Item] in (' + Stuff((Select ','+QuoteName(concat('InsuranceNo',ColNr))
From (Select Distinct ColNr=row_number() over (Partition By MemberID Order By (Select NULL)) from YourTable ) A
For XML Path('')),1,1,'') + ') ) p'
--Print #SQL
Exec(#SQL);
Returns
MemberID InsuranceNo1 InsuranceNo2
123456 dser abcd
124571 jklh NULL
If it helps wrap your head around PIVOT, the SQL Generated looks like this:
Select *
From (
Select MemberID
,Item = concat('InsuranceNo',row_number() over (Partition By MemberID Order By (Select NULL)))
,Value = InsuranceNo
From YourTable
) A
Pivot (max([Value]) For [Item] in ([InsuranceNo1],[InsuranceNo2]) ) p
I prefer a dynamic cross tab to the dynamic pivot. I find the syntax far less obtuse and it is super easy if you need to add additional columns. Here is I would go about tackling this. Of course in your case you don't need a temp table because you have an actual table to use.
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
MemberID int
, InsuranceNo varchar(10)
)
insert #Something values
(123456, 'dser')
, (124571, 'jklh')
, (123456, 'abcd')
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by MemberID order by InsuranceNo) as RowNum
from #Something
)
select MemberID';
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by MemberID order by MemberID';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then InsuranceNo end) as InsuranceNo' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by MemberID
order by COUNT(*) desc
)
select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute

how to display data with dynamic columns -SQL

I have a dynamic pivot query that has dynamic columns column1, column 2... column
My query works fine. I can dump it into temp table ... But I wanted a view. I can't because of the changing number of columns. What do I do? It took long time to put this query together as I am not sql expert.
I would like to have a view of the result so I can link it to Access for the teams. I also have to create more queries in Access based on this link so the link can not disconnect. Any help will be appreciated
Below is my query.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ','
+ QUOTENAME(case
when d.col = 'OriginalDx' then col+cast(seq as varchar(10))
else 'OriginalDx'+cast(seq as varchar(10))+'_'+col end)
from
(
select row_number() over(partition by [HCCCodingBASEID]
order by [HCCCodingBASEID]) seq
from [IDEAApplication].[HCCCoding].[OriginalDiagnosis]
) t
cross apply
(
select 'OriginalDx', 1
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT [HCCCodingBASEID] AS ORIGINALDX_ID, ' + #cols + '
from
(
select t.[HCCCodingBASEID],
col = case
when c.col = ''OriginalDx'' then col+cast(seq as varchar(10))
else ''OriginalDx''+cast(seq as varchar(10))+''_''+col
end,
value
from
(
select [HCCCodingBASEID], [OriginalDiagnosisCD],
row_number() over(partition by [HCCCodingBASEID]
order by [HCCCodingBASEID]) seq
from [IDEAApplication].[HCCCoding].[OriginalDiagnosis]
) t
cross apply
(
select ''OriginalDx'', [OriginalDiagnosisCD]
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p '
----execute sp_executesql #query;
DECLARE #cols1 AS NVARCHAR(MAX),
#query1 AS NVARCHAR(MAX)
select #cols1 = STUFF((SELECT ','
+ QUOTENAME(case
when d.col = 'DxAdded' then col+cast(seq as varchar(10))
else 'DxAdded'+cast(seq as varchar(10))+'_'+col end)
from
(
select row_number() over(partition by [HCCCodingBASEID]
order by [AddDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[AddDiagnosis]
) t1
cross apply
(
select 'DxAdded', 1 union all
select 'Reason', 2
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query1 = 'SELECT [HCCCodingBASEID] AS DXADDED_ID, ' + #cols1 + '
from
(
select t1.[HCCCodingBASEID],
col = case
when c.col = ''DxAdded'' then col+cast(seq as varchar(10))
else ''DxAdded''+cast(seq as varchar(10))+''_''+col
end,
value
from
(
select [HCCCodingBASEID], [AddDiagnosisCD], [AddReasonTXT],
row_number() over(partition by [HCCCodingBASEID]
order by [AddDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[AddDiagnosis]
) t1
cross apply
(
select ''DxAdded'', [AddDiagnosisCD] union all
select ''Reason'', [AddReasonTXT]
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols1 + ')
) p '
------------------------------------------------------------------
DECLARE #cols2 AS NVARCHAR(MAX),
#query2 AS NVARCHAR(MAX)
select #cols2 = STUFF((SELECT ','
+ QUOTENAME(case
when d.col = 'DxDeleted' then col+cast(seq as varchar(10))
else 'DxDeleted'+cast(seq as varchar(10))+'_'+col end)
from
(
select row_number() over(partition by [HCCCodingBASEID]
order by [DeleteDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[DeleteDiagnosis]
) t2
cross apply
(
select 'DxDeleted', 1 union all
select 'Reason', 2
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query2 = 'SELECT [HCCCodingBASEID] AS DXDELETED_ID, ' + #cols2 + '
-----into ##tmp2
from
(
select t2.[HCCCodingBASEID],
col = case
when c.col = ''DxDeleted'' then col+cast(seq as varchar(10))
else ''DxDeleted''+cast(seq as varchar(10))+''_''+col
end,
value
from
(
select [HCCCodingBASEID], [DeleteDiagnosisCD], [DeleteReasonTXT],
row_number() over(partition by [HCCCodingBASEID]
order by [DeleteDiagnosisCD]) seq
from [IDEAApplication].[HCCCoding].[DeleteDiagnosis]
) t2
cross apply
(
select ''DxDeleted'', [DeleteDiagnosisCD] union all
select ''Reason'', [DeleteReasonTXT]
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols2 + ')
) p '
-----------------------------------------------------merge all tables
----IF OBJECT_ID('tempdb..##TMP') IS NOT NULL
---DROP TABLE ##TMP
DECLARE #cmd NVARCHAR(MAX);
SET #cmd=N'
SELECT top 100 percent
A.*,
BB.PatientID as [Epic PatientID],
convert (varchar (10),AA.BirthDTS,101) as [Birth Date],
AA.SexDSC as [Sex],
BB.HospitalAccountBaseClassDSC as [Patient Type],
EE.payorNM AS [Payor Name],
B.*,
C.*,
D.*
--INTO ##TMP
FROM
[IDEAApplication].[HCCCoding].[HCCCoding] as A
LEFT JOIN ('+#query+') AS B
ON A.ID=B.ORIGINALDX_ID
LEFT JOIN ('+#query1+') AS C
ON A.ID=C.DXADDED_ID
LEFT JOIN ('+#query2+') AS D
ON A.ID=D.DXDELETED_ID
LEFT OUTER JOIN Epic.Finance.HospitalAccount_Enterprise AS BB
ON A.HospitalAccountID = BB.HospitalAccountID
LEFT JOIN Epic.Patient.Patient_Enterprise AS AA
ON BB.PatientID =AA.PatientID
LEFT JOIN Epic.Finance.HospitalAccount3_Enterprise AS CC
ON BB.HospitalAccountID = CC.HospitalAccountID
LEFT JOIN Epic.Reference.Payor AS EE
ON BB.PrimaryPayorID = EE.PayorID
order BY A.ID
;
';
EXECUTE (#cmd)

converting and concatenating multiple rows into columns

I am using Dynamic PIVOT approach to convert the dynamic rows into columns and its working fine for me. But I have one more requirement on top of it. I am using below query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ','
+ QUOTENAME(case when d.col = 'STN_CODE' then col+'_'+cast(seq as varchar(10))
else col+'_'+cast(seq as varchar(10)) end)
from ( select row_number() over(partition by POF_FILE_ID,
PART_PFX,
PART_BASE,PART_SFX
order by STN_CODE,PROCESS_ELEMENT) seq
from APT_POINT_OF_FIT
) t
cross apply
(
select 'STN_CODE', 1 union all
select 'PROCESS_ELEMENT', 2
) d (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT POF_FILE_ID,PART_PFX,PART_BASE,PART_SFX, ' +
#cols + '
from
(
select t.POF_FILE_ID,t.PART_PFX,t.PART_BASE,t.PART_SFX,
col = case
when c.col = ''STN_CODE'' then col+''_''+cast(seq as varchar(10))
else col+''_''+cast(seq as varchar(10))
end,
value
from
(
select POF_FILE_ID,PART_PFX,PART_BASE,PART_SFX,STN_CODE,
PROCESS_ELEMENT,
row_number() over(partition by POF_FILE_ID,
PART_PFX,
PART_BASE,
PART_SFX
order by STN_CODE) seq
from APT_POINT_OF_FIT
) t
cross apply
(
select ''STN_CODE'', STN_CODE union all
select ''PROCESS_ELEMENT'', PROCESS_ELEMENT
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute sp_executesql #query;
My requirement is to insert the values in separate columns till seq 8 and concatenate all other column values coming after that seq(> seq8).
Any help would be appreciated.
Thanks!

converting rows to columns dynamicaly based on conditions

In the below image I have current data and expected data based on the first three columns the data need to get transpose
Table query:
drop table ##Test
CREATE TABLE ##Test
(paymentid varchar(30),
claimid bigint,
Lineno1 int,
groupcode varchar(2),
Carc int,
adjustmentamt float,
RARC varchar(30),
Edit1 varchar(30),
Remit varchar(30),
)
INSERT INTO ##Test
(paymentid ,
claimid ,
Lineno1 ,
groupcode ,
Carc ,
adjustmentamt ,
RARC ,
Edit1 ,
Remit )
VALUES
('QP18502291',14205893514,2,'CO',84,75.55,'N20','','D18')
('QP15930339',14127612308,1,'OA',23,263,'','ClaimDetail.COBAmt','') ,
('QP15930339',14127612308,1,'OA',23,21.69,'','ClaimDetail.COBAmt',''),
('QP18502291',14205893514,2,'OA',23,78.77,'','ClaimDetail.COBAmt',''),
('QP18502291',14205893514,2,'OA',97,66.55,'N20','','D18')
select * from ##Test
Possible duplicate post and take a look at the solution.
See SQL Fiddle with Demo.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(col+cast(rn as varchar(10)))
from
(
select row_number() over(partition by paymentid order by Lineno1) rn
from ##Test
) d
cross apply
(
select 'groupcode', 1 union all
select 'carc', 2 union all
select 'adjustmentamt', 3 UNION ALL
SELECT 'rarc',4 UNION ALL
SELECT 'Edit1' ,5 UNION ALL
SELECT 'remit',6
) c (col, so)
group by col, rn, so
order by rn, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT paymentid, claimid,Lineno1,' + #cols + '
from
(
select paymentid, claimid,Lineno1, col+cast(rn as varchar(10)) col, value
from
(
select paymentid, claimid,Lineno1, groupcode, carc, adjustmentamt,rarc,Edit1,remit,
row_number() over(partition by paymentid order by Lineno1) rn
from ##Test
) t
cross apply
(
select ''groupcode'', groupcode union all
select ''carc'', cast(carc as varchar(50)) union all
select ''adjustmentamt'', cast(adjustmentamt as varchar(50)) union all
select ''rarc'', rarc union all
select ''Edit1'' , Edit1 union all
select ''remit'' , remit
) c (col, value)
) x pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute(#query)