If you are on a version of SQL Server prior to 2016, you will need to create your own String Splitting function and reference that in your script. The version I use is as follows:
create function [dbo].[StringSplit]
(
@str nvarchar(4000) = ' ' -- String to split.
,@delimiter as nvarchar(1) = ',' -- Delimiting value to split on.
,@num as int = null -- Which value to return.
)
returns table
as
return
( -- Start tally table with 10 rows.
with n(n) as (select n from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n(n))
-- Select the same number of rows as characters in @str as incremental row numbers.
-- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length.
,t(t) as (select top (select len(@str) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4)
-- Return the position of every value that follows the specified delimiter.
,s(s) as (select 1 union all select t+1 from t where substring(@str,t,1) = @delimiter)
-- Return the start and length of every value, to use in the SUBSTRING function.
-- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string.
,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,@str,s),0)-s,4000) from s)
select rn as ItemNumber
,Item
from(select row_number() over(order by s) as rn
,substring(@str,s,l) as item
from l
) a
where rn = @num -- Return a specific value where specified,
or @num is null -- Or the everything where not.
)
And is used as follows. Note that I have split the outer apply
into separate queries to avoid row duplication:
declare @t table(OrderNo int,Customers nvarchar(500),Amount nvarchar(500));
insert into @t values
(1,'Briant~~Luck','23~~2122')
,(2,'Mike~~Lee~~David','10~~200~~37')
,(3,'Stak','100');
with c as
(
select t.OrderNo
,c.ItemNumber
,c.Item as Customers
from @t t
outer apply dbo.StringSplit(replace(t.Customers,'~~','|'),'|',null) c
),a as
(
select t.OrderNo
,a.ItemNumber
,a.Item as Amount
from @t t
outer apply dbo.StringSplit(replace(t.Amount,'~~','|'),'|',null) a
)
select c.OrderNo
,c.Customers
,a.Amount
from c
join a
on(c.OrderNo = a.OrderNo
and c.ItemNumber = a.ItemNumber
)
order by a.OrderNo
,c.Customers;
Output:
+---------+-----------+--------+
| OrderNo | Customers | Amount |
+---------+-----------+--------+
| 1 | Briant | 23 |
| 1 | Luck | 2122 |
| 2 | David | 37 |
| 2 | Lee | 200 |
| 2 | Mike | 10 |
| 3 | Stak | 100 |
+---------+-----------+--------+