【问题标题】:SQL Server : Split string to rowSQL Server:将字符串拆分为行
【发布时间】:2017-04-25 19:13:27
【问题描述】:

如何从下面转换数据:

CODE COMBINATION   USER
1111.111.11.0      KEN; JIMMY
666.778.0.99       KEN
888.66.77.99       LIM(JIM); JIMMY

CODE COMBINATION   USER
1111.111.11.0      KEN
1111.111.11.0      JIMMY
666.778.0.99       KEN
888.66.77.99       LIM(JIM)
888.66.77.99       JIMMY

我知道在 SQL Server 2016 中这可以通过拆分字符串函数来完成,但我的生产是 SQL Server 2014。

【问题讨论】:

    标签: tsql split sql-server-2014


    【解决方案1】:

    使用此 TVF,您可以提供要拆分和分隔符的字符串。此外,您还可以获得对二次处理非常有用的序列号。

    Select [CODE COMBINATION]
          ,[USER] = B.RetVal
     From  YourTable A
     Cross Apply [dbo].[udf-Str-Parse](A.[USER],';') B
    

    返回

    解析 UDF

    CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
    Returns Table 
    As
    Return (  
        Select RetSeq = Row_Number() over (Order By (Select null))
              ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
        From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
        Cross Apply x.nodes('x') AS B(i)
    );
    --Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
    --Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
    

    现在,另一个选项是 Parse-Row UDF。请注意,我们在一行中返回已解析的字符串。目前9个职位,但很容易扩展或收缩。

    Select [CODE COMBINATION]
          ,B.*
     From  YourTable A
     Cross Apply [dbo].[udf-Str-Parse-Row](A.[USER],';') B
    

    返回

    解析行 UDF

    CREATE FUNCTION [dbo].[udf-Str-Parse-Row] (@String varchar(max),@Delimiter varchar(10))
    Returns Table 
    As
    Return (
        Select Pos1 = xDim.value('/x[1]','varchar(max)')
              ,Pos2 = xDim.value('/x[2]','varchar(max)')
              ,Pos3 = xDim.value('/x[3]','varchar(max)')
              ,Pos4 = xDim.value('/x[4]','varchar(max)')
              ,Pos5 = xDim.value('/x[5]','varchar(max)')
              ,Pos6 = xDim.value('/x[6]','varchar(max)')
              ,Pos7 = xDim.value('/x[7]','varchar(max)')
              ,Pos8 = xDim.value('/x[8]','varchar(max)')
              ,Pos9 = xDim.value('/x[9]','varchar(max)')
         From (Select Cast('<x>' + Replace(@String,@Delimiter,'</x><x>')+'</x>' as XML) as xDim) A
    )
    --Select * from [dbo].[udf-Str-Parse-Row]('Dog,Cat,House,Car',',')
    --Select * from [dbo].[udf-Str-Parse-Row]('John Cappelletti',' ')
    

    【讨论】:

      【解决方案2】:

      您需要使用 UDF 在每一行上拆分它

      CREATE FUNCTION [DBO].[FN_SPLIT_STR_TO_COL] (@T AS VARCHAR(4000) )
      RETURNS
       @RESULT TABLE(VALUE VARCHAR(250))
      AS
      BEGIN
           SET @T= @T+';'
             ;WITH MYCTE(START,[END]) AS(
      
          SELECT 1 AS START,CHARINDEX(';',@T,1) AS [END]
          UNION ALL
          SELECT [END]+1 AS START,CHARINDEX(';',@T,[END]+1)AS [END] 
          FROM MYCTE WHERE [END]<LEN(@T)
          )
          INSERT INTO @RESULT 
          SELECT SUBSTRING(@T,START,[END]-START) NAME FROM MYCTE;
      
            RETURN 
      END
      

      现在通过CROSS APPLY调用上面的函数来查询你的表

        SELECT [CodeCombination],FN_RS.VALUE FROM TABLE1
        CROSS APPLY
       (SELECT * FROM [DBO].[FN_SPLIT_STR_TO_COL] (User))           
        AS FN_RS
      

      【讨论】:

      • 为什么要投反对票??请解释一下,否则你的反对票没有用
      【解决方案3】:

      如果您的 [USER] 列只有一个分号,则根本不需要“拆分字符串”功能;你可以像这样使用 CROSS APPLY:

      -- Your Sample data 
      DECLARE @table TABLE (CODE_COMBINATION varchar(30), [USER] varchar(100));
      INSERT @table
      VALUES ('1111.111.11.0', 'KEN; JIMMY'), ('666.778.0.99', 'XKEN'),
             ('888.66.77.99','LIM(JIM); JIMMY');
      
      -- Solution using only CROSS APPLY
      SELECT CODE_COMBINATION, [USER] = LTRIM(s.s)
      FROM @table t
      CROSS APPLY (VALUES (CHARINDEX(';',t.[USER]))) d(d)
      CROSS APPLY 
      (
        SELECT SUBSTRING(t.[USER], 1, ISNULL(NULLIF(d.d,0),1001)-1)
        UNION ALL
        SELECT SUBSTRING(t.[USER], d.d+1, 1000)
        WHERE d.d > 0
      ) s(s);
      

      如果您确实需要 SQL Server 2016 之前的“拆分字符串”功能,我强烈建议您使用 Jeff Moden 的 DelimitedSplit8k 或 Eirikur Eiriksson 的 DelimitedSplit8K_LEAD。这两者都将优于基于 XML 或递归 CTE“拆分字符串”功能。

      【讨论】:

        猜你喜欢
        • 2016-10-11
        • 1970-01-01
        • 1970-01-01
        • 2014-12-12
        • 2016-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多