拆分字符串而不创建新表或string_split()

时间:2018-11-02 21:03:51

标签: sql sql-server

我的字符串实际上只有一个规则:总是有一个'/'分隔符,其频率为2。

示例:

1/2/3

111/222222/3

asdf/dd/eds

如何在没有string_split()的情况下执行此操作或创建新表以将该字符串分成3个?

我做了几次尝试,但是总有些不正确。

在下面的示例中,假设“ str”是上述示例之一。

select
    substring(str,0,charindex('/',str,0)) as first, 
    substring(str,charindex('/',str,0) + 1,charindex('/',strcharindex('/',strcharindex('/',str,0) + 1))) as 2nd,
    --3rd

4 个答案:

答案 0 :(得分:2)

我发现使用apply最简单:

select v1.first, v2.second, v2.third
from (values ('a/b/c')) t(str) cross apply
     (values (left(t.str, charindex('/', t.str) - 1),
              stuff(t.str, 1, charindex('/', t.str), '')
             )
     ) v1(first, rest) cross apply
     (values (left(v1.rest, charindex('/', v1.rest) - 1),
              stuff(v1.rest, 1, charindex('/', v1.rest), '')
             )
     ) v2(second, third);

Here是db <>小提琴。

您可以将stuff()left()视为substring()的简写。

还有其他选择,例如split()函数。不幸的是,内置的split函数没有为生成的字符串提供索引。因此,您可以获得零件,但无法按顺序购买。

您还可以使用递归CTE和XML设计解决方案。对于这种特定的问题,我只是喜欢使用这种方法。

答案 1 :(得分:2)

根据您的要求,但不需要LEN()

declare @var varchar(64) = '111/222222/3'

select 
    substring(@var,1,charindex('/',@var) - 1)
    ,substring(@var,charindex('/',@var) + 1,charindex('/',substring(@var,charindex('/',@var) + 1,99)) - 1)
    ,substring(substring(@var,charindex('/',@var) + 1,99),charindex('/',substring(@var,charindex('/',@var) + 1,99)) + 1,99)

在任何地方看到99都会将其更改为字符串的最大长度,或者将8000更改为字符串全部

答案 2 :(得分:2)

在这种情况下,最简单的解决方案是(ab)使用parsename-使用cross applyreplace

SELECT PARSENAME(val, 3) As col1,
       PARSENAME(val, 2) As col2,
       PARSENAME(val, 1) As col3
FROM Table
CROSS APPLY
(
    SELECT REPLACE(str, '/', '.') As val
) x

在马丁·史密斯(Martin Smith)评论之后-

只有在定界符之间的字符串不超过128个字符且不包含点的情况下,这才起作用(尽管这可以用更多的replace语句解决,但这会使整个事情变得更麻烦)

答案 3 :(得分:2)

另一个选择是一点XML

示例

Declare @YourTable table (SomeCol varchar(50))
Insert Into @YourTable values
('1/2/3')
,('111/222222/3')
,('asdf/dd/eds')


Select A.*
      ,B.*
 From  @YourTable 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)')
                From  (Select Cast('<x>' + replace((Select replace(SomeCol,'/','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as B1
             ) B

返回

SomeCol       Pos1  Pos2    Pos3
1/2/3         1     2       3
111/222222/3  111   222222  3
asdf/dd/eds   asdf  dd      eds