SQL拆分字符串(所有可能的组合)

SQL拆分字符串(所有可能的组合),sql,sql-server,string,split,Sql,Sql Server,String,Split,我想转换此字符串: A1+A2+A3.B1+B2.C1 进入 A1.B1.C1 A1.B2.C1 A2.B1.C1 A2.B2.C1 A3.B1.C1 A3.B2.C1 我该怎么做?请注意,每个维度=一个由…分隔的组,可以有x个值,我的意思是它可以是A1+A2.B1.C1或A1+A2.B1+B2+B3+B4+B5.C1+C2 谢谢这是SQL server版本和: 将LST作为字符串“A1+A2.B1+B2+B3+B4+B5.C1+C2”中的select* 从中选择t1+'.+t2+'.+t3作为

我想转换此字符串: A1+A2+A3.B1+B2.C1 进入 A1.B1.C1 A1.B2.C1 A2.B1.C1 A2.B2.C1 A3.B1.C1 A3.B2.C1

我该怎么做?请注意,每个维度=一个由…分隔的组,可以有x个值,我的意思是它可以是A1+A2.B1.C1或A1+A2.B1+B2+B3+B4+B5.C1+C2


谢谢

这是SQL server版本和:

将LST作为字符串“A1+A2.B1+B2+B3+B4+B5.C1+C2”中的select* 从中选择t1+'.+t2+'.+t3作为res select*from STRING_SPLITS从lst中选择s,其中s类似于“A%”、“+”s1t1交叉连接 从字符串中选择*从lst中选择s,其中s类似于“B%”、“+”s2t2交叉连接 从字符串中选择*从lst中选择s,其中s类似于“C%”、“+”s3t3; 当然,如果维度数量增加,您可以按常规方式对其进行增长

以下是Postgresql解决方案:

使用xs作为选择字符串_到_数组'A1+A2.B1+B2+B3+B4+B5.C1+C2',' 选择t1 | |'.| | t2 | |'.| | t3作为res from unnestselect字符串_到_数组[1],“+”从x t1交叉连接 unnestselect字符串_到_数组[2],“+”从x t2交叉连接 unnest从x t3选择字符串_到_数组[3],“+”; 结果:

res     |
--------|
A1.B1.C1|
A1.B2.C1|
A1.B3.C1|
A1.B4.C1|
A1.B5.C1|
A2.B1.C1|
A2.B2.C1|
A2.B3.C1|
A2.B4.C1|
A2.B5.C1|
A1.B1.C2|
A1.B2.C2|
A1.B3.C2|
A1.B4.C2|
A1.B5.C2|
A2.B1.C2|
A2.B2.C2|
A2.B3.C2|
A2.B4.C2|
A2.B5.C2|

如果只有3列,则只需使用:从第一次拆分开始为组编号,然后执行3次联接,并选择相应联接上的每个组

with a as  (
 select s2.value as v, dense_rank() over(order by s1.value) as rn
  from STRING_SPLIT('A1+A2+A3.B1+B2.C1', '.') as s1
        cross apply STRING_SPLIT(s1.value, '+') as s2
)
select
  a1.v + '.' + a2.v + '.' + a3.v as val
from a as a1
  cross join a as a2
  cross join a as a3
where a1.rn = 1
  and a2.rn = 2
  and a3.rn = 3
如果组的数量不确定,那么最好使用动态SQL而不是动态SQL。你应该做什么:

从第一组中的所有值开始。 递归步骤交叉连接下一组的所有值,即步骤组编号为当前组编号+1。 选择将得到结果的最后一个递归步骤。 代码如下:

with a as  (
 select s2.value as v, dense_rank() over(order by s1.value) as rn
  from STRING_SPLIT('A1+A2+A3.B1+B2+B3+B4.C1+C2.D1+D2+D3', '.') as s1
        cross apply STRING_SPLIT(s1.value, '+') as s2
)
, b (val, lvl) as (
  /*Recursion base*/
  select cast(v as nvarchar(1000)) as val, rn as lvl
  from a
  where rn = 1

  union all
  /*Increase concatenation on each iteration*/
  select cast(concat(b.val, '.', a.v) as nvarchar(1000)) as val, b.lvl + 1 as lvl
  from b
    join a
      on b.lvl + 1 = a.rn /*Recursion step*/
)
select *
from b
where lvl = (select max(rn) from a) /*You need the last step*/
order by val

我不会添加表格结果,因为它相当大。但是。

在您的帮助下,这里是我的代码。我没有提到,但我也可以有多于或少于3个部分,因此我使用动态SQL来实现这一点:


用您正在使用的数据库标记您的问题。大多数数据库都有一些拆分功能。你试过什么吗?另外,请检查这个:我会查看字符串分割和交叉连接。太多了,太完美了!!这是我的代码和你的帮助。我没有提到,但我也可以有多于或少于3个部分,因此我使用动态SQL来实现这一点:@user11051593我已经为非任意数量的组更新了答案,但没有任何动态SQL。
with a as  (
 select s2.value as v, dense_rank() over(order by s1.value) as rn
  from STRING_SPLIT('A1+A2+A3.B1+B2+B3+B4.C1+C2.D1+D2+D3', '.') as s1
        cross apply STRING_SPLIT(s1.value, '+') as s2
)
, b (val, lvl) as (
  /*Recursion base*/
  select cast(v as nvarchar(1000)) as val, rn as lvl
  from a
  where rn = 1

  union all
  /*Increase concatenation on each iteration*/
  select cast(concat(b.val, '.', a.v) as nvarchar(1000)) as val, b.lvl + 1 as lvl
  from b
    join a
      on b.lvl + 1 = a.rn /*Recursion step*/
)
select *
from b
where lvl = (select max(rn) from a) /*You need the last step*/
order by val
declare @FILTER varchar(max)='B+C+D.A+G.T+Y+R.E' 
-- Works also with A.B.C
-- Works also with A+B+C.D.E+F
-- Works also with A+B+C.D+E+F+G+H
declare @NB int
declare @SQL varchar(max)=''

select @NB=count(*) from STRING_SPLIT(@FILTER,'.')


set @SQL='
;with T(A,B) as
    (select *, row_number() over (order by (select NULL)) 
     from STRING_SPLIT(''' + @FILTER + ''',''.'')
     )
     select '

;with T(V,N) as (
    select *, row_number() over (order by (select NULL))
    from STRING_SPLIT(@FILTER,'.')
)
select @SQL=@SQL + 'T' + cast(N as varchar(max)) + ' + ''.'' + ' from T
set @SQL=left(@SQL,len(@SQL)-1) + ' as res from'

;with T(V,N) as (
    select *, row_number() over (order by (select NULL))
    from STRING_SPLIT(@FILTER,'.')
)
select @SQL=@SQL + '
(select * from STRING_SPLIT((select A from T where B=' + cast(N as varchar(max)) + '),     ''+'')) s' + cast(N as varchar(max)) + '(t' + cast(N as varchar(max)) + ') cross join'
from T

set @SQL=left(@SQL,len(@SQL)-len('cross join'))
exec(@SQL)