Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split multiple comma separated columns into rows

I have one table (SQL Server), which has comma separated values in multiple columns, like below:

Rule_ID    ListType_ID    Values
1          1,2            100,200
2          3,4            300,400

I want to split the comma separated values and convert them into rows.

The required output must be like below:

Rule_ID    ListType_ID    Values
1          1              100
1          2              200
2          3              300
2          4              400

I have tried the below query:

DECLARE @TEMP AS TABLE (
    [Rule_ID] INT,
    [ListType_ID] VARCHAR(MAX),
    [Values] VARCHAR(MAX)
)

INSERT INTO @TEMP
SELECT 1, '1,2', '100,200'
UNION ALL
SELECT 2, '3,4', '300,400' 

SELECT 
    [Rule_ID],
    PARSENAME(REPLACE(Split1.b.value('.', 'VARCHAR(100)'),'-','.'),1) AS [ListType_ID],
    PARSENAME(REPLACE(Split.a.value('.', 'VARCHAR(100)'),'-','.'),1) AS [Values] 
FROM  
(
    SELECT [Rule_ID],
    CAST ('<M>' + REPLACE([ListType_ID], ',', '</M><M>') + '</M>' AS XML) AS [ListType_ID],
    CAST ('<M>' + REPLACE([Values], ',', '</M><M>') + '</M>' AS XML) AS [Values] 
    FROM @TEMP     
) AS A 
CROSS APPLY [Values].nodes ('/M') AS Split(a)
CROSS APPLY [ListType_ID].nodes ('/M') AS Split1(b)
ORDER BY [Rule_ID], [ListType_ID], [Values]

This query returns the below output, which is different from the required output:

Rule_ID    ListType_ID    Values
1          1              100
1          1              200
1          2              100
1          2              200
2          3              300
2          3              400
2          4              300
2          4              400

Please help me here....!!!!

like image 825
Sandeep Kumar Avatar asked Mar 07 '23 03:03

Sandeep Kumar


2 Answers

Please check following SQL script

To split string in SQL I used one of the following user-defined SQL split string functions

These functions return the order of the splitted string which I used in WHERE clause so I can map field values one-to-one

/*
create table Table_1 (
    Rule_ID int,    ListType_ID    varchar(max), [Values] varchar(max)
)
insert into Table_1 select 1,'1,2','100,200'
insert into Table_1 select 2,'3,4','300,400'
*/
select 
Rule_ID,
idlist.val as ListType_ID,
valueslist.val as [Values]
from Table_1
cross apply dbo.SPLIT(ListType_ID,',') as idlist
cross apply dbo.SPLIT([Values],',') as valueslist
where 
idlist.id = valueslist.id
like image 197
Eralper Avatar answered Mar 16 '23 09:03

Eralper


Using CTE, a double CROSS APPLY and XML based split you can use this script:

;WITH Splitted AS 
( 
    SELECT    
        [Rule_ID]
        ,CAST('<x>' + REPLACE([ListType_ID],',','</x><x>') + '</x>' AS XML) AS  [ListType_ID_Val]    
        ,CAST('<x>' + REPLACE([Values],',','</x><x>') + '</x>' AS XML) AS  [Values_Val]    
    FROM @TEMP 
) 
SELECT     
    Rule_ID, cs.VAL as[ListType_ID], cd.VAL as [Values]
FROM Splitted
    CROSS APPLY (VALUES ('a',ListType_ID_Val.value(N'/x[1]','int') ),
      ('b',ListType_ID_Val.value(N'/x[2]','int') )
    )CS (COL,VAL) 
     CROSS APPLY (VALUES ('a',Values_Val.value(N'/x[1]','int') ),
      ('b',Values_Val.value(N'/x[2]','int') )
    )CD (COL,VAL) 
where CS.COL = CD.COL

Results:

enter image description here

like image 38
Andrea Avatar answered Mar 16 '23 08:03

Andrea