I am trying to separate strings into different columns which are separated by commas. I tried all the article that is on stackoverflow but not successful.
Example:
Column1
mouse,monitor,keyboard
cable,mouse
headset,desk,cable,monitor,usb,charger
Expected results:
Column1 |Column2 |Column3 |Column4 |Column5 |Column6
mouse |monitor |keyboard | NULL | NULL | NULL
cable |mouse |NULL | NULL | NULL | NULL
headset |desk |cable | monitor | usb | charger
Please note that the strings under Column1 can be as many as 10 strings and the strings are different every week so they are undefined.
This is one of the code I tried:
Declare #TblName (id int, Column1 varchar(max))
Insert into #TblName
Select A.Column1
,B.*
From #TblNameK A
Cross Apply (
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + Replace(A.Column1,',','</x><x>')+'</x>' as XML) as xDim) A
) B
You can use XML method below :
DECLARE
#t TABLE (keywords VARCHAR(MAX) )
INSERT INTO #t VALUES
('mouse,monitor,keyboard'),
('cable,mouse'),
('headset,desk,cable,monitor,usb,charger'),
('M&M,Hot&Cold,sneakers')
SELECT
ROW_NUMBER() OVER(ORDER BY keywords DESC) ID
, keywords
FROM (
SELECT
LTRIM(RTRIM(m.n.value('.[1]','VARCHAR(8000)'))) keywords
FROM (
SELECT CAST('<Root><Keyword>' + REPLACE(REPLACE(keywords,'&','&') ,',','</Keyword><Keyword>') + '</Keyword></Root>' AS XML) keywords
FROM #t
) D
CROSS APPLY keywords.nodes('/Root/Keyword')m(n)
) C
This will put each keyword in a row. From there you can count the number of keywords and do further stuff on them (like getting the distinct values, pivot them ..etc).
Since you are using SQL Server 2016, you can use the built-in string_split() function:
declare #t table (Value varchar(max));
insert into #t (Value)
values
('mouse,monitor,keyboard'),
('cable,mouse'),
('headset,desk,cable,monitor,usb,charger')
;
select *
from #t t
cross apply string_split(t.Value, ',') ss;
Having all the values in one column will be especially handy if you are actually going to get some aggregated statistics out of them.
Related
I am trying to do this in SQL: data in column is like this need to separate them into new columns.
Create table #TEST4 ( NAME VARCHAR(25) )
INSERT INTO #TEST4
VALUES ( 'a,b,c,d,e')
,( 'ax,bde,c,ded,es')
select name from #TEST4
Expecting result like this, any suggestions will be appreciated.
enter image description here
Using a bit of JSON in concert with a CROSS APPLY
Select Name1 = JSON_VALUE(JS,'$[0]')
,Name2 = JSON_VALUE(JS,'$[1]')
,Name3 = JSON_VALUE(JS,'$[2]')
,Name4 = JSON_VALUE(JS,'$[3]')
From #TEST4 A
Cross Apply (values ( '["'+replace(string_escape(NAME,'json'),',','","')+'"]' ) ) B(JS)
Results
Name1 Name2 Name3 Name4
a b c d
ax bde c ded
Update: XML Approach
Select Name1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)'))) -- choose the proper datatype
,Name2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Name3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
,Name4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
From #Test4 A
Cross Apply ( values (cast('<x>' + replace((Select replace(NAME,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml))) B(xDim)
I've got a text field on a table that I'm trying to dissect into two separate columns in a select statement. I swear this worked for me last time I used it, but now it's throwing an error "Invalid length parameter". What am I doing wrong?
Splitting the data from a single column which is like this:
"CORP - DIVISION - REGION - TEAM - SUPERVISOR"
Into two columns like:
SUPERVISOR | TEAM
Here's what I had that I swear used to work, but it doesn't anymore and I can't figure it out!
Reverse(Left(Reverse(table.column),CHARINDEX(' ', Reverse(table.column))-1)) AS 'SUPERVISOR'
,LTRIM(LEFT(Substring(table.column,18,150),CHARINDEX(' - ', Substring(table.column,18,150))-1)) AS 'TEAM'
If you have a known or maximum number of items, consider a little XML. Perhaps a little easier to read and maintain.
Also, you could eliminate Pos1,Pos2,Pos3 if you are only interested in Team & Supervisor.
Example
Declare #YourTable Table ([ID] varchar(50),[SomeCol] varchar(50))
Insert Into #YourTable Values
(1,'CORP - DIVISION - REGION - TEAM - SUPERVISOR')
Select A.ID
,B.*
From #YourTable A
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(100)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(100)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(100)')))
,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(100)')))
,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(100)')))
,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(100)')))
,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(100)')))
,Pos8 = ltrim(rtrim(xDim.value('/x[8]','varchar(100)')))
,Pos9 = ltrim(rtrim(xDim.value('/x[9]','varchar(100)')))
From (Select Cast('<x>' + replace(SomeCol,'-','</x><x>')+'</x>' as xml) as xDim) as A
) B
Returns
ID Pos1 Pos2 Pos3 Pos4 Pos5 Pos6 Pos7 Pos8 Pos9
1 CORP DIVISION REGION TEAM SUPERVISOR NULL NULL NULL NULL
EDIT
If you have non XML safe characters (<,>,,...) use
...
From ( values (cast('<x>' + replace((Select replace(SomeCol,'-','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml))) A(xDim)
...
From SQL Server 2016 you can use STRING_SPLIT() to do it.
The STRING_SPLIT() can help normalize the data by splitting these
multi-valued columns.
I also used TRIM() function (introduced with SQL Server 2017) in order to remove the spaces, CTE, ROW_NUMBER() and PIVOT.
Below the script:
—-1 Create a test table
CREATE TABLE #TestTable
(
TestColumn varchar(100)
)
—-2 Inserting your string into table
INSERT INTO #TestTable
VALUES ('0 - CORP - DIVISION - REGION - TEAM - SUPERVISOR')
--3 Final query
;WITH CTE_Table AS (
SELECT
TestColumn = TRIM(TestColumn)
FROM
#TestTable
)
,CTE_Table2 AS (
SELECT
S.Value
FROM
CTE_Table
CROSS APPLY STRING_SPLIT([TestColumn],'-') AS S
)
,CTE_FinalTable AS (
SELECT TOP 5
Value
,ROW_NUMBER() OVER (ORDER BY Value) AS RowNumber
FROM
CTE_Table2
ORDER BY
Value
)
SELECT
[1],[2],[3],[4],[5]
FROM
CTE_FinalTable
PIVOT
(MAX([value])
The FOR [RowNumber] IN ([1],[2],[3],[4],[5])
) AS P
In T-SQL I have a column with some text in it with a format like the following:
[Key1:Value1:Value2:Value3:Value4:Value5]
[Key2:Value1:Value2:Value3:Value4:Value5]
[Key3:Value1:Value2:Value3:Value4:Value5]
where there can be any number of bracket sets, but usually between 3 and 6. I'm looking for a way to quickly format them into a temp table or table variable so I can report on the data. For example, I'd want the table format to be:
|Key|Column 1|Column 2|Column 3|Column 4|Column 5|
|Key 1|Value 1|Value 2|Value 3|Value 4|Value 5|
|Key 2|Value 1|Value 2|Value 3|Value 4|Value 5|
|Key 3|Value 1|Value 2|Value 3|Value 4|Value 5|
I know this is pushing the limits of SQL and should be handled through modification of the application, but I'm hoping there's something clever I can do with T-SQL for now.
If you have a maximum number of columns, a little XML within a CROSS APPLY.
If unknown, you would have to go DYNAMIC.
Example
Declare #YourTable Table ([ID] varchar(50),[SomeCol] varchar(50))
Insert Into #YourTable Values
(1,'[Key1:Value1:Value2:Value3:Value4:Value5]')
,(2,'[Key2:Value1:Value2:Value3:Value4:Value5]')
,(3,'[Key3:Value1:Value2:Value3:Value4:Value5]')
Select A.ID
,B.*
From #YourTable A
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
,Pos8 = ltrim(rtrim(xDim.value('/x[8]','varchar(max)')))
,Pos9 = ltrim(rtrim(xDim.value('/x[9]','varchar(max)')))
From (Select Cast('<x>' + replace(replace(replace(SomeCol,'[',''),']',''),':','</x><x>')+'</x>' as xml) as xDim) as A
) B
Returns
ID Pos1 Pos2 Pos3 Pos4 Pos5 Pos6 Pos7 Pos8 Pos9
1 Key1 Value1 Value2 Value3 Value4 Value5 NULL NULL NULL
2 Key2 Value1 Value2 Value3 Value4 Value5 NULL NULL NULL
3 Key3 Value1 Value2 Value3 Value4 Value5 NULL NULL NULL
EDIT
I should add, the ltrim(rtrim(...)) is optional and the varchar(max) is my demonstrative default.
EDIT - One String delimited with CRLF
Declare #S varchar(max)='
[Key1:Value1:Value2:Value3:Value4:Value5]
[Key2:Value1:Value2:Value3:Value4:Value5]
[Key3:Value1:Value2:Value3:Value4:Value5]
'
Select B.*
From (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace(#S,char(13)+char(10),'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) A
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
,Pos8 = ltrim(rtrim(xDim.value('/x[8]','varchar(max)')))
,Pos9 = ltrim(rtrim(xDim.value('/x[9]','varchar(max)')))
From (Select Cast('<x>' + replace(replace(replace(RetVal,'[',''),']',''),':','</x><x>')+'</x>' as xml) as xDim) as A
) B
Where A.RetVal is not null
The fastest way to split a string when you know the maximum number of columns is to use the Cascading CROSS APPLY technique. Let's say you know that their will be no more than 10 items in your string. You could do this:
DECLARE #string varchar(1000) = '[Key1:Value1:Value2:Value3:Value4:Value5]'
SELECT
[key] = SUBSTRING(t.string,1,d1.d-1),
col1 = SUBSTRING(t.string,d1.d+1,d2.d-d1.d-1),
col2 = SUBSTRING(t.string,d2.d+1,d3.d-d2.d-1),
col3 = SUBSTRING(t.string,d3.d+1,d4.d-d3.d-1),
col4 = SUBSTRING(t.string,d4.d+1,d5.d-d4.d-1),
col5 = SUBSTRING(t.string,d5.d+1,d6.d-d5.d-1),
col6 = SUBSTRING(t.string,d6.d+1,d7.d-d5.d-1),
col7 = SUBSTRING(t.string,d7.d+1,d8.d-d5.d-1),
col8 = SUBSTRING(t.string,d8.d+1,d9.d-d5.d-1),
col9 = SUBSTRING(t.string,d9.d+1,d10.d-d5.d-1)
FROM (VALUES (REPLACE(REPLACE(#string,']',':'),'[',''))) t(string)
CROSS APPLY (VALUES (CHARINDEX(':',t.string))) d1(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d1.d+1),0))) d2(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d2.d+1),0))) d3(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d3.d+1),0))) d4(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d4.d+1),0))) d5(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d5.d+1),0))) d6(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d6.d+1),0))) d7(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d7.d+1),0))) d8(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d8.d+1),0))) d9(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d9.d+1),0))) d10(d);
To use this technique against a table with the strings stored in rows would be like this:
DECLARE #table TABLE (someid int identity, somestring varchar(1000));
INSERT #table(somestring) VALUES
('[Key1:Value1:Value2:Value3:Value4:Value5]'),
('[Key2:Value1:Value2:Value3:Value4:Value5]'),
('[Key3:Value1:Value2:Value3:Value4:Value5]'),
('[Key4:Value1:Value2:Value3:Value4:Value5:Value6:Value7:Value8]'),
('[Key5:Value1:Value2:Value3:Value4:Value5:Value6:Value7:Value8:Value9:Value10]');
SELECT *
FROM #table s
CROSS APPLY
(
SELECT
[key] = SUBSTRING(t.string,1,d1.d-1),
dCount = LEN(t.string)-LEN(REPLACE(t.string,':','')),
col1 = SUBSTRING(t.string,d1.d+1,d2.d-d1.d-1),
col2 = SUBSTRING(t.string,d2.d+1,d3.d-d2.d-1),
col3 = SUBSTRING(t.string,d3.d+1,d4.d-d3.d-1),
col4 = SUBSTRING(t.string,d4.d+1,d5.d-d4.d-1),
col5 = SUBSTRING(t.string,d5.d+1,d6.d-d5.d-1),
col6 = SUBSTRING(t.string,d6.d+1,d7.d-d6.d-1),
col7 = SUBSTRING(t.string,d7.d+1,d8.d-d7.d-1),
col8 = SUBSTRING(t.string,d8.d+1,d9.d-d8.d-1),
col9 = SUBSTRING(t.string,d9.d+1,d10.d-d9.d-1)
FROM (VALUES (REPLACE(REPLACE(s.somestring,']',':'),'[',''))) t(string)
CROSS APPLY (VALUES (CHARINDEX(':',t.string))) d1(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d1.d+1),0))) d2(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d2.d+1),0))) d3(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d3.d+1),0))) d4(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d4.d+1),0))) d5(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d5.d+1),0))) d6(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d6.d+1),0))) d7(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d7.d+1),0))) d8(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d8.d+1),0))) d9(d)
CROSS APPLY (VALUES (NULLIF(CHARINDEX(':',t.string,d9.d+1),0))) d10(d)
) split
WHERE LEN(s.somestring)-LEN(REPLACE(s.somestring,':','')) < 10
If you don't know the maximum number of possible items you could take this logic and wrap it in some Dynamic SQL that creates the correct number of CROSS APPLY's. I don't have time to put together that logic but, to get the maximum number of possible delimiters you could do something like this:
DECLARE #maxDelimiters tinyint =
(SELECT MAX(LEN(s.somestring)-LEN(REPLACE(s.somestring,':',''))) FROM #table s);
Alternatively, if you wanted to use John's technique, you could also use Dynamic SQL to create his query with the exact number of "pos" values required.
I have an email column with 3-4 emails in each row which i want to split into one email per column:
Current columns looks like this:
Email_column
1. drone#gmail.com bob#yahoo.com drake#gmail.com
Expected output should be:
Email_1 Email_2 Email_3
1. drone#email.com bob#yahoo.com drake#gmail.com
With a CROSS APPLY and a little XML
Example
Declare #YourTable table (ID int,Email_column varchar(max))
Insert Into #YourTable values
(1,'drone#gmail.com bob#yahoo.com drake#gmail.com')
Select A.ID
,B.*
From #YourTable A
Cross Apply (
Select Pos1 = n.value('/x[1]','varchar(max)')
,Pos2 = n.value('/x[2]','varchar(max)')
,Pos3 = n.value('/x[3]','varchar(max)')
,Pos4 = n.value('/x[4]','varchar(max)')
From (Select Cast('<x>' + replace(A.Email_column,' ','</x><x>')+'</x>' as xml) as n) X
) B
Returns
ID Pos1 Pos2 Pos3 Pos4
1 drone#gmail.com bob#yahoo.com drake#gmail.com NULL
I have the following table
Col
=========================
1270.8/847.2/254.16/106.9
And I would like to be split into columns like so:
Col1 Col2 Col3 Col4
============================================
1270.8 847.2 254.16 106.9
I have the code below, but it doesn't take the decimal into consideration.
Declare #Sample Table
(MachineName varchar(max))
Insert into #Sample
values ('1270.8/847.2/254.16');
SELECT
Reverse(ParseName(Replace(Reverse(MachineName), '/', ''), 1)) As [M1]
, Reverse(ParseName(Replace(Reverse(MachineName), '/', ''), 2)) As [M2]
, Reverse(ParseName(Replace(Reverse(MachineName), '/', ''), 3)) As [M3]
FROM #Sample
In SQL Server 2016+ you can use string_split().
In SQL Server pre-2016, using a CSV Splitter table valued function by Jeff Moden and conditional aggregation:
declare #Sample Table (id int not null identity(1,1), MachineName varchar(max));
insert into #Sample values ('1270.8/847.2/254.16'),('1270.8/847.2/254.16/106.9');
select
t.id
, m1 = max(case when s.ItemNumber = 1 then s.Item end)
, m2 = max(case when s.ItemNumber = 2 then s.Item end)
, m3 = max(case when s.ItemNumber = 3 then s.Item end)
, m4 = max(case when s.ItemNumber = 4 then s.Item end)
from #Sample t
cross apply dbo.delimitedsplit8K(MachineName,'/') s
group by id
rextester demo: http://rextester.com/WJVLB77682
returns:
+----+--------+-------+--------+-------+
| id | m1 | m2 | m3 | m4 |
+----+--------+-------+--------+-------+
| 1 | 1270.8 | 847.2 | 254.16 | NULL |
| 2 | 1270.8 | 847.2 | 254.16 | 106.9 |
+----+--------+-------+--------+-------+
splitting strings reference:
Tally OH! An Improved SQL 8K “CSV Splitter” Function - Jeff Moden
Splitting Strings : A Follow-Up - Aaron Bertrand
Split strings the right way – or the next best way - Aaron Bertrand
string_split() in SQL Server 2016 : Follow-Up #1 - Aaron Bertrand
Everyone should have a good split/parse function as illustrated by SQLZim (+1), but another option could be as follow:
Declare #YourTable table (ID int,Col varchar(max))
Insert Into #YourTable values
(1,'1270.8/847.2/254.16/106.9')
Select A.ID
,B.*
From #YourTable A
Cross Apply (
Select Col1 = xDim.value('/x[1]','float')
,Col2 = xDim.value('/x[2]','float')
,Col3 = xDim.value('/x[3]','float')
,Col4 = xDim.value('/x[4]','float')
From (Select Cast('<x>' + replace((Select replace(A.Col,'/','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A
) B
Returns
ID Col1 Col2 Col3 Col4
1 1270.8 847.2 254.16 106.9
EDIT - If 2012+, and just to be super-duper safe
Select A.ID
,B.*
From #YourTable A
Cross Apply (
Select Col1 = try_convert(float,xDim.value('/x[1]','varchar(100)'))
,Col2 = try_convert(float,xDim.value('/x[2]','varchar(100)'))
,Col3 = try_convert(float,xDim.value('/x[3]','varchar(100)'))
,Col4 = try_convert(float,xDim.value('/x[4]','varchar(100)'))
From (Select Cast('<x>' + replace((Select replace(A.Col,'/','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A
) B
If you are using SQL Server 2016, you can use String_Split()
;with cte as (
select RowN = row_number() over(order by (SELECT NULL)), * from string_split('1270.8/847.2/254.16/106.9','/')
) select * from cte
pivot (max(value) for RowN in ([1],[2],[3],[4])) p
If you are using less than SQL Server 2016 version then you might require to use custom split functions... Many ways to write custom split function one easier way is to write using xml
CREATE Function dbo.udf_split( #str varchar(max), #delimiter as varchar(5) )
RETURNS #retTable Table
( RowN int,
value varchar(max)
)
AS
BEGIN
DECLARE #xml as xml
SET #xml = cast(('<X>'+replace(#str,#delimiter ,'</X><X>')+'</X>') as xml)
INSERT INTO #retTable
SELECT RowN = Row_Number() over (order by (SELECT NULL)), N.value('.', 'varchar(MAX)') as value FROM #xml.nodes('X') as T(N)
RETURN
END
--Your query
;with cte as (
select * from udf_split('1270.8/847.2/254.16/106.9','/')
) select * from cte
pivot (max(value) for RowN in ([1],[2],[3],[4])) p
But mine is similar to John's solution... Just now only looking at that
If you are using in value in a table then you can use cross apply as below
create table #t (v varchar(50), i int)
insert into #t (v, i) values ('1270.8/847.2/254.16/106.9',1)
,('847.222/254.33/106.44',2)
select * from #t t cross apply string_split(t.v, '/')
create table #t (v varchar(50), i int)
insert into #t (v, i) values ('1270.8/847.2/254.16/106.9',1)
,('847.222/254.33/106.44',2)
--Just to get all the values
select * from #t t cross apply string_split(t.v, '/')
--Inorder to get into same row -pivoting the data
select * from (
select * from #t t cross apply (select RowN=Row_Number() over (Order by (SELECT NULL)), value from string_split(t.v, '/') ) d) src
pivot (max(value) for src.RowN in([1],[2],[3],[4])) p