sql multiple row from column value - sql

i have table with one column having comma seperated values and I want in row..
like
col1
3,4,5
5,6,6
return result should be
col1
3
4
5
5
6
6

declare #tbl table(data nvarchar(100))
insert into #tbl values('1,2,3')
insert into #tbl values('4,5,6')
insert into #tbl values('7,8,9')
SELECT
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT data,
CAST ('<M>' + REPLACE(data, ',', '</M><M>') + '</M>' AS XML) AS String
FROM #tbl) AS A CROSS APPLY String.nodes ('/M') AS Split(a);

I believe the below explains how to loop through comma separated values. You could just insert them into another variable to get your required output.
Splitting of comma separated values

You can use a recursive query to perform this split:
;with cte (item, list) as
(
select
cast(left(col1, charindex(',',col1+',')-1) as varchar(50)) item,
stuff(col1, 1, charindex(',',col1+','), '') list
from yourtable
union all
select
cast(left(list, charindex(',',list+',')-1) as varchar(50)) item,
stuff(list, 1, charindex(',',list+','), '') list
from cte
where list > ''
)
select item
from cte
See SQL Fiddle with Demo

Related

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....!!!!
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
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:

SQL Server import row string to table columns

I have a table containing the following text per row
"[0,0,0,1,2,4,1,0,0,2,0,0,0,0,847,18207,0,0,0,0,0,0,0,0,0,0,0,0]"
Now i want to insert these 28 values in a table containing 28 columns. I tried a few split functions but these would return only rows.
Any ideas?
using dbo.fnParseString()
INSERT INTO a_table (col1, col2, col3, . . . )
SELECT dbo.fnParseString(-1, ',', str)
,dbo.fnParseString(-2, ',', str)
,dbo.fnParseString(-3, ',', str)
,....
FROM yourtable
DECLARE #x XML
;with cte as (
SELECT '[0,0,0,1,2,4,1,0,0,2,0,0,0,0,847,18207,0,0,0,0,0,0,0,0,0,0,0,0]' as col
)
SELECT #x= (
SELECT CAST('<s>' + REPLACE(REPLACE(REPLACE(col,'[','<a>'),']','</a>'),',','</a><a>') +'</s>'AS XML)
FROM cte
FOR XML PATH('')
)
SELECT t.v.value('a[1]','int'),
t.v.value('a[2]','int'),
t.v.value('a[3]','int'),
...
t.v.value('a[28]','int')
FROM #x.nodes('/s') as t(v)

how to write SQL query for this result?

I have so many long database so I used seq_no in commas separate using more than one sequence store in single column but now I want all sequence in a single column so I am confused how to create this sql result for this.
For example:
TABLE STRUCTURE
SR_NO IS INT ,
SEQ_NO IS VARCHAR(MAX)
SR_NO SEQ_NO
---------------------------------
1 1839073,
2 1850097,1850098,
3 1850099,1850100,1850110
I need to get this result:
SEQ_NO
--------------
1839073
1850097
1850098
1850099
1850100
1850110
Thanks!
declare #t table(Id int,seq varchar(100))
insert into #t (Id,seq) values (1,'1839073,'),(2,'1839073,1850098,'),(3,'1850099,1850100,1850110 ')
;With Cte as (
SELECT A.Id,
Split.a.value('.', 'VARCHAR(100)') AS Seq
FROM
(
SELECT Id,
CAST ('<M>' + REPLACE(seq, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #t
) AS A CROSS APPLY Data.nodes ('/M') AS Split(a) )
Select ID,Seq from Cte Where Seq > ''
Try splitting it with XML
SELECT SR_NO, t.c.value('.', 'VARCHAR(2000)') COL1
FROM (
SELECT SR_NO, x = CAST('<t>' +
REPLACE(SEQ_NO, ',', '</t><t>') + '</t>' AS XML)
FROM
(values(1,'1839073'),(2, '1850097,1850098'),
(3, '1850099,1850100,1850110')) y(SR_NO, SEQ_NO)
) a
CROSS APPLY x.nodes('/t') t(c)
Result:
SR_NO COL1
1 1839073
2 1850097
2 1850098
3 1850099
3 1850100
3 1850110
You can replace this with your table:
(values (1,'1839073'),(2, '1850097,1850098'),
(3, '1850099,1850100,1850110')) y(SR_NO, SEQ_NO)
This should do it: (Replace YourTableName with your table name)
;WITH CTE(NEW_SEQ_NO, SEQ_NO) as (
SELECT LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO + ',') -1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO + ','), '')
FROM YourTableName
WHERE SEQ_NO <> '' AND SEQ_NO IS NOT NULL
UNION all
SELECT LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO + ',') -1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO + ','), '')
FROM CTE
WHERE SEQ_NO <> '' AND SEQ_NO IS NOT NULL
)
SELECT NEW_SEQ_NO from CTE ORDER BY NEW_SEQ_NO
You can check this topic for more information:
Turning a Comma Separated string into individual rows
I have written the following query after referring Turning a Comma Separated string into individual rows
It will work for you
create table STRUCTURE(SR_NO int, SEQ_NO varchar(max))
insert STRUCTURE select 1, '1839073,'
insert STRUCTURE select 2, '1850097,1850098,'
insert STRUCTURE select 3, '1850099,1850100,1850110'
;with tmp(SR_NO, DataItem, SEQ_NO) as (
select SR_NO, LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO+',')-1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO+','), '')
from STRUCTURE
union all
select SR_NO, LEFT(SEQ_NO, CHARINDEX(',',SEQ_NO+',')-1),
STUFF(SEQ_NO, 1, CHARINDEX(',',SEQ_NO+','), '')
from tmp
where SEQ_NO > ''
)
Select DataItem as SEQ_NO from tmp order by SEQ_NO;

Inserting multiple value in table with String input

I am passing one string to store procedure : 1:20,2:30,4:50
It contains id and appropriate value for it.
how can I add value as shown in below table in database.
ID Value
1 20
2 30
4 50
I have already "stringSplit" function which works perfectly and gives out put in row value some think like this :
1:20
2:30
4:50
can anyone please help me to insert data into table with any solution.
i already try this solution
insert <table> (colname)
select y.item
from dbo.SplitString(#testString, ':') x
cross apply
dbo.SplitString(x.item, ',') y
but this will return duplicate value as more as id value.
my store procedure is
CREATE PROCEDURE [dbo].[temp_result_insert]
#dataString varchar(max)
AS
insert into tempTable(id,marks)
select x.Item,y.Item
from dbo.SplitStringVarcahr(#dataString, ':') x
cross apply
dbo.SplitStringVarcahr(x.Item,',') y
RETURN 0
As you already splitted into rows and you want insert into some table by splliting into two columns may be this works
CREATE TABLE #Test(ID INT,Val INT)
declare #t table (val varchar(50))
insert into #t (val)values ('1:20,2:30,4:50')
declare #str varchar(max)
;with cte as (
SELECT
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT
CAST ('<M>' + REPLACE([val], ',', '</M><M>') + '</M>' AS XML) AS String
FROM #t) AS A CROSS APPLY String.nodes ('/M') AS Split(a))
INSERT INTO #Test
select SUBSTRING(String,0,CHARINDEX(':',String)),REVERSE(SUBSTRING(reverse(String),0,CHARINDEX(':',reverse(String)))) from cte
select * from #test
You can also try XML.nodes() and string functions to spit the data. Something like this
DECLARE #var VARCHAR(100) = '1:20,2:30,4:50'
DECLARE #xml xml = CONVERT(xml, '<r>' + REPLACE(#var,',','</r><r>') + '</r>')
SELECT LEFT(val,cindex - 1) c1,RIGHT(val,LEN(val) - cindex) c2
FROM
(
SELECT CHARINDEX(':',c.value('text()[1]','VARCHAR(100)')) cindex,c.value('text()[1]','VARCHAR(100)') val
FROM #xml.nodes('r') as t(c))c
Use substring and Charindex:
SELECT Substring(col, 0, Charindex(col, ':') - 1) AS id,
Substring(col, Charindex(col, ':') + 1, Len(col)-Charindex(col, ':')) AS value
FROM splittedtable

Getting latest data in a table from comma separated value joining with original table

I have created script to get the comma separated value, that value(cloumn1) joined with another table(column2), (column1) having n number of duplicate I want to get the latest top 1 from column1 and join with column2. script ->
SELECT A.EmailHistoryid,
Split.a.value('.', 'VARCHAR(100)') AS String,
A.MailTo
INTO #tmp
FROM (
SELECT EmailHistoryid,
CAST('<M>' + REPLACE([requestinstanceids], ',', '</M><M>') + '</M>' AS XML) AS String,
MailTo
FROM [emailhistoryDT] NOLOCK
) AS A
CROSS APPLY String.nodes('/M') AS Split(a)
ORDER BY a.EmailHistoryid DESC;