Create table test123
(
SeqId int,
string1 varchar(100),
string2 varchar(100)
)
insert into test123(SeqId,string1,string2)values
(10,'a,b,c','x,y,z'),
(20,'d,e,f','p,q,r')
输出
SeqId RowNum String1 String2
10 1 a x
10 2 b y
10 3 c z
20 1 d p
20 2 e q
20 3 f r
最佳答案
这将允许字符串中的项目数量可变/不均匀。
几乎任何拆分/解析函数都可以。我提供了一份,其中还提供了该项目的序列号。
选项 1:不使用解析函数
Declare @YourTable table (SeqId int,string1 varchar(100),string2 varchar(100))
insert into @YourTable values
(10,'a,b,c','x,y,z'),
(20,'d,e,f','p,q,r')
Select A.SeqId
,B.*
From @YourTable A
Cross Apply (
Select RowNum = RetSeq
,String1 = max(String1)
,String2 = max(String2)
From (
Select RetSeq = Row_Number() over (Order By (Select null))
,String1 = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
,String2 = ''
From (Select x = Cast('<x>' + replace((Select replace(A.String1,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
Union All
Select RetSeq = Row_Number() over (Order By (Select null))
,String1 = ''
,String2 = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(A.String2,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B1
Group By RetSeq
) B
选项 2:使用解析函数
Declare @YourTable table (SeqId int,string1 varchar(100),string2 varchar(100))
insert into @YourTable values
(10,'a,b,c','x,y,z'),
(20,'d,e,f','p,q,r')
Select A.SeqId
,B.*
From @YourTable A
Cross Apply (
Select RowNum = RetSeq
,String1= max(String1)
,String2= max(String2)
From (
Select RetSeq,String1=RetVal,String2='' from [dbo].[udf-Str-Parse](A.string1,',')
Union All
Select RetSeq,String1='',String2=RetVal from [dbo].[udf-Str-Parse](A.string2,',')
) B1
Group By RetSeq
) B
两者均返回
UDF(如果有兴趣)
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(25))
Returns Table
As
Return (
with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
cte3(N) As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)
Select RetSeq = Row_Number() over (Order By A.N)
,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
From cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
关于SQL,from ,分隔行到列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43622240/