Reputation: 143
I have the following table in my database where two of the columns has comma separated string. I want to split the columns based on comma and insert the string in the database as a row. Below is my table and insert statements:
CREATE TABLE [dbo].[TABLEA](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DocNumber] [varchar](50) NULL,
[InternalDocNumber] [varchar](50) NULL,
[Date] [varchar](50) NULL,
[DocType] [varchar](50) NULL,
[Description] [varchar](50) NULL,
[NameG] [varchar](max) NULL,
[NameGR] [varchar](max) NULL,
[NumberPages] [varchar](50) NULL)
Below are the insert statements in the table:
INSERT INTO [dbo].[TABLEA]
([DocNumber]
,[InternalDocNumber]
,[Date]
,[DocType]
,[Description]
,[NameG]
,[NameGR]
,[NumberPages])
VALUES
(1
,1235
,'12/23/2020'
,3
,'this is a test'
,'test1, test2, test3'
,'test6, test4'
,1),
(2
,3456
,'12/24/2020'
,3
,'this is a test1'
,'test4, test5, test6'
,'test9, test4'
,2)
,
(6
,6789
,'12/24/2020'
,3
,'this is a test3'
,'test9'
,'test100, test15, test16'
,2)
GO
From the above table. I want to create a new table that have a result like below:
ID DocNumber InternalDocnumber date DocType Description NameG NameGR NumberPage
1 1 1235 12/23/2020 3 thisisaTest test1 test6 1
1 1 1235 12/23/2020 3 thisisaTest test2 test4 1
1 1 1235 12/23/2020 3 thisisaTest test3 NULL 1
2 2 3456 12/24/2020 3 thisisaTest1 test4 test9 2
2 2 3456 12/24/2020 3 thisisaTest1 test5 test4 2
2 2 3456 12/24/2020 3 thisisaTest1 test6 NULL 2
3 6 6789 12/24/2020 3 thisisaTest3 test9 test100 2
3 6 6789 12/24/2020 3 thisisaTest3 NULL test15 2
3 6 6789 12/24/2020 3 thisisaTest3 NULL test16 2
Basically, I want the comma delimited string that is present in column NameG and NameGR to be splitted on comma based and then insert in a new table as anew row. The order is very important, if there is "Test1" in NameG column then here should be "Test6" in columnGR.
Any help with this will be highly appreciated.
Upvotes: 0
Views: 412
Reputation: 121
use the function Call STRING_SPLIT
SELECT ID,value AS NameG
FROM TABLEA
CROSS APPLY STRING_SPLIT(NameG, ',')
with this function the separated comma values are separated but with the relation of the ID
then we look for the relationship with the id of tablea
WITH DataSplit as
(
SELECT ID,value AS NameG
FROM TABLEA
CROSS APPLY STRING_SPLIT(NameG, ',')
)
select TABLEA.Id,TABLEA.DocNumber,TABLEA.InternalDocNumber,TABLEA.Date,
TABLEA.DocType,TABLEA.Description, DataSplit.NameG
from TABLEA inner join DataSplit on TABLEA.id=DataSplit.id;
see the example in fiddler for more detail
Upvotes: 1
Reputation: 23797
with gx as
(select [Id], [NameG],
row_number() over (partition by [id] order by [Id]) as rNo
from (select [Id] ,ltrim(x.Value) as [NameG]
from tablea
cross apply string_split(nameG, ',') as x) g),
grx as (
select [Id], [NameGR],
row_number() over (partition by [Id] order by [Id]) as rNo
from
(select [Id] ,ltrim(x.Value) as [NameGR]
from tablea
cross apply string_split(nameGR, ',') as x) gr),
names (Id, NameG, NameGR, r1, r2) as
( select coalesce(gx.Id, grx.Id), gx.NameG, grx.NameGR, coalesce(gx.rNo, grx.rNo), coalesce(grx.rNo, gx.rNo)
from gx
full join grx on gx.Id = grx.Id and gx.rNo = grx.rNo)
select a.Id
,[DocNumber]
,[InternalDocNumber]
,[Date]
,[DocType]
,[Description]
,n.[NameG]
,n.[NameGR]
,[NumberPages]
from tableA a
inner join names n on a.Id = n.Id
order by a.Id, r1, r2;
Upvotes: 1
Reputation: 1269753
This is a pain in SQL Server, because strint_split()
doesn't provide a number or even a guaranteed ordering. So instead, use a recursive CTE:
with cte as (
select a.docnumber, convert(varchar(max), null) as gr, convert(varchar(max), null) as g,
convert(varchar(max), nameGR) as restGR, convert(varchar(max), nameG) as restG, 0 as lev
from tableA a
union all
select cte.docnumber,
left(restgr, charindex(',', restgr + ',') - 1) as gr,
left(restg, charindex(',', restg + ',') - 1) as g,
stuff(restgr, 1, charindex(',', restgr + ',') + 1, '') as restgr,
stuff(restg, 1, charindex(',', restg + ',') + 1, '') as restg,
lev + 1
from cte
where restgr > '' or restg > ''
)
select id, gr, g
from cte
where lev > 0;
Here is a db<>fiddle.
This only shows the one docnumber
column. You can add the rest of the columns. I think they just confuse the presentation.
Upvotes: 1