【问题标题】:SQL Server - How to split strings on a character in multiple columnsSQL Server - 如何在多列中拆分字符上的字符串
【发布时间】:2018-03-28 04:14:47
【问题描述】:

我需要拆分由波浪号 (~) 字符分隔的列中的值,但对于单行中的多个列。我可以使用 XML 拆分一列,但在弄清楚如何拆分多列时遇到了问题。

这是一行当前的样子:

Column1    Column2               Column3                  Column4     
[JJ2222]   [~BLUE~BROWN~BLACK]   [~BB1234~BC2345~BD3456]  [~BLUE, BABY (BB1234)~BROWN, COW (BC2345)~BLACK, DOG (BD3456)]

拆分后,我期望多行的所有值在锚点上对齐 (JJ2222):

Column1  Column2  Column3  Column4
JJ2222   BLUE     BB1234   BLUE, BABY (BB1234)
JJ2222   BROWN    BC2345   BROWN, COW (BC2345)
JJ2222   BLACK    BD3456   BLACK, DOG (BD3456)

以我有限的知识,我可能会创建 3 个单独的查询,将每个列分别拆分并加载到一个临时表中,然后在 Column1 上加入每个表,但我希望有一种方法可以在一个查询中完成。

【问题讨论】:

  • 有几十个重复的说法相同:避免首先插入这样的值。加载数据时拆分字符串要容易得多。您无法索引或搜索此类列。 SQL Server 在 2016 年添加了一个STRING_SPLIT 命令,可用于清理此类条目
  • Panagiotis - 感谢您的建议。是的,我对2016年添加的String_Split函数很熟悉,但不幸的是,这个版本是2012年。

标签: sql-server split


【解决方案1】:

有很多关于如何拆分字符串的示例。这里的技巧是链接或加入序列。

如果对 UDF 开放

示例

Select A.Column1 
      ,B.* 
 From  YourTable A
 Cross Apply (
                Select Column2=B1.RetVal
                      ,Column3=B2.RetVal
                      ,Column4=B3.RetVal
                 From [dbo].[tvf-Str-Parse](A.Column2,'~') B1
                 Join [dbo].[tvf-Str-Parse](A.Column3,'~') B2 on B1.RetSeq=B2.RetSeq
                 Join [dbo].[tvf-Str-Parse](A.Column4,'~') B3 on B1.RetSeq=B3.RetSeq
                 Where B1.RetVal is not null
                   and B2.RetVal is not null
                   and B3.RetVal is not null
             ) B

退货

Column1 Column2 Column3 Column4
JJ2222  BLUE    BB1234  BLUE, BABY (BB1234)
JJ2222  BROWN   BC2345  BROWN, COW (BC2345)
JJ2222  BLACK   BD3456  BLACK, DOG (BD3456)

有兴趣的 UDF

CREATE FUNCTION [dbo].[tvf-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((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
--Thanks Shnugo for making this XML safe
--Select * from [dbo].[tvf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[tvf-Str-Parse]('John Cappelletti was here',' ')

【讨论】:

  • 谢谢约翰!您的脚本运行良好。它完全符合我的要求。
  • @RonnieJ 乐于助人
【解决方案2】:

既然搞砸了,让它变成一个不同的(稍微小一点的)也无济于事。您需要将这些数据拆分到不同的表中。

除了第 1 列之外的所有内容都需要成为另一个表的外键。

对于原始表中的列中的每个项目组合,您使用适当的附加表。这些表中的每一个看起来像:

组合标识、值

当你得到例如:

[~BLUE~BROWN~BLACK]

你把它分解成额外的表格组合2,比如:

CombinationId Value

1 BLUE

1 BROWN

1 BLACK

您对原始表格的所有列执行此操作。当您为每一列逐行处理原始表时,您检查是否在您创建的新表 CombinationsX 中已经存在类似共享相同 ID 的组合。如果是这样,您将该 ID 放在原始表中。如果不是,则将该组合添加到新索引中,并将该数字作为外键放入原始表中。

您现在已将数据拆分为多个表并使其可用。

从现在开始你想做的事情会有所不同,但至少你现在可以把它改造成不同的东西。至少现在您可以查询该数据、搜索、索引等。当您没有用垃圾填充数据库时,您期望从数据库中为您提供的东西;)

【讨论】:

    【解决方案3】:

    这是我非常喜欢 Jeff Moden 的分离器的时候之一。 http://www.sqlservercentral.com/articles/Tally+Table/72993/ 这是我所知道的唯一一个返回每个不诉诸循环的元素的序数位置的拆分器之一。如 cmets 所述,尽可能不存储这样的数据是迄今为止最好的选择。要解决此问题,您必须拆分每一列。

    这应该对你有用。它适用于您的示例数据。

    declare @Something table
    (
        Column1 varchar(20)
        , Column2 varchar(50)
        , Column3 varchar(50)
        , Column4 varchar(500)
    )
    
    insert @Something
    select 'JJ2222', '~BLUE~BROWN~BLACK', '~BB1234~BC2345~BD3456', '~BLUE, BABY (BB1234)~BROWN, COW (BC2345)~BLACK, DOG (BD3456)'
    ;
    
    select s.Column1
        , c2.Item
        , c3.Item
        , c4.Item
    from @Something s
    cross apply dbo.DelimitedSplit8K(s.Column2, '~') c2
    cross apply dbo.DelimitedSplit8K(s.Column3, '~') c3
    cross apply dbo.DelimitedSplit8K(s.Column4, '~') c4
    where c2.Item > ''  --this eliminates an empty row because you have the delimiter at the beginning of the string.
        and c2.ItemNumber = c3.ItemNumber
        and c2.ItemNumber = c4.ItemNumber
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      相关资源
      最近更新 更多