Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
282 views
in Technique[技术] by (71.8m points)

sql - Split string into multiple rows with multiple columns in paired

I have a table as below:

Order No | Customers            | Amount    
---------+----------------------+-------------
1        | Briant~~Luck         | 23~~2122 
2        | Mike~~Lee~~David     | 10~~200~37 
3        | Stak                 | 100

With format, each customer has one value in Amount.

I'm trying to figure out how to expand the ~~ delimited values to populate a new customers table, which should look like this:

Order No | Customer             | Amount    
---------+----------------------+---------
1        | Briant               |   23
1        | Luck                 | 2122 
2        | Mike                 |   10 
2        | Lee                  |  200
2        | David                |   37 
3        | Stak                 |  100

How can I do?

Any solution in SQL query, function or cursor is appreciated.

Thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think you could store data as your expected result structure. It is much better.
Btw you could use a split function to get your output

DECLARE @SampleData AS TABLE
(
    OrderNo int,
    Customers varchar(200),
    Amount varchar(200)
)

INSERT INTO @SampleData
(
    OrderNo,
    Customers,
    Amount
)
VALUES
( 1, 'Briant~~Luck','23~~2122'), 
( 2, 'Mike~~Lee~~David','10~~200~~37'),
( 3, 'Stak','100')


SELECT sd.OrderNo, c.[Value] AS Customer, a.[Value] AS Amount
FROM @SampleData sd
CROSS APPLY 
(
    SELECT Pos, Value
    FROM [dbo].[SplitString](sd.Customers,'~~')
) c
CROSS APPLY 
(
    SELECT Pos, Value
    FROM [dbo].[SplitString](sd.Amount,'~~')
) a
WHERE c.Pos = a.Pos
ORDER BY sd.OrderNo

Split function

CREATE FUNCTION [dbo].[SplitString] (@Text varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
   Select Pos = Row_Number() over (Order By (Select null))
        ,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
   From (Select x = Cast('<x>'+ Replace(@Text,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
   Cross Apply x.nodes('x') AS B(i)
);

Demo link: http://rextester.com/XRX32958


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...