【问题标题】:T-SQL splitting column on a delimiter [duplicate]分隔符上的 T-SQL 拆分列 [重复]
【发布时间】:2018-12-08 00:16:42
【问题描述】:

我有一列包含由正斜杠分隔的三组数据,就像这样

AB/1234/10

每一行中的列格式始终相同,包含 2 个字符、一个斜线、一些字符、一个斜线,然后是另外 2 个字符。我需要将这一列分成三列。所以上面的例子就变成了

Column1 Column2 Column3
AB      1234    10

我不太确定该怎么做。我一直在使用SELECT SUBSTRING,但这并不能满足我的需求。

select SUBSTRING(MyColumn, 1, CHARINDEX('/', MyColumn, 1)-1) 
FROM MyTable

将返回AB,这很好。但我不知道如何抓住中间部分和末端部分。我以为

select SUBSTRING(MyColumn, 4, CHARINDEX('/', MyColumn, 4)) 
FROM MyTable

可以抓住中间,但它返回1234/10

我希望我的问题很清楚,如果有任何建议可以为我指明正确的方向,我将不胜感激,谢谢。

【问题讨论】:

  • 理想情况下,此练习的一部分应该是永久分离这些数据。像这样存储多个元素违反了 1NF,并且使用起来非常痛苦。
  • 如果您在建议的副本中使用拆分器,您应该避免接受的答案,因为它是拆分字符串的一种糟糕方式。而是向下滚动到 Aaron Bertrand 的答案。它的性能要好得多。

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

您可以使用固定偏移量,因为您定义了字符串始终以两个字符开头,并以两个字符结尾。

这是一个完整的工作示例:

DECLARE @tmp TABLE (
  Merged nvarchar(max)
)

INSERT INTO @tmp SELECT N'AB/1234/10'
INSERT INTO @tmp SELECT N'AB/ANYNUMBEROF-CHARACTERS/10'

SELECT
  LEFT(Merged,2) AS Column1,
  SUBSTRING(Merged,4,LEN(Merged)-6) AS Column2,
  RIGHT(Merged,2) AS Column3
FROM @tmp

我们减去字符串的长度减去一个常数(6 = 左两个字符,右两个字符,两个斜杠)以从中间提取可变长度部分。

结果:

列 1 列 2 列 3 AB 1234 10 AB 任意字符 10

【讨论】:

    【解决方案2】:

    一种方法是使用PARSENAME

    SELECT PARSENAME(REPLACE('AB/1234/10','/','.'), 3) Col1,
           PARSENAME(REPLACE('AB/1234/10','/','.'), 2) Col2,
           PARSENAME(REPLACE('AB/1234/10','/','.'), 1) Col3
    

    这会将/ 替换为.,并用PARSENAME 拉出字符串的每个部分。

    好处是它可以在任何位置处理任何长度的字符。限制是 PARSENAME 最多只能处理 4 个位置(在这种情况下,您使用的是 3 个),如果字符串中已经存在句点 . 则会失败。

    【讨论】:

    • 我非常喜欢这个技巧,但是如果任何源字符串包含一个点,它就会失败。
    • 处理句点的一种简单方法是先添加替换以换出 .像^这样的东西。当然,你必须把它换回去,对于这个简单的来说,哪种开始有点过头了。
    • 不幸的是,我的任何或所有字符串都可以包含.,所以虽然这个答案很好,但它不适用于我的情况。不过还是谢谢。
    【解决方案3】:

    试试这个。这应该适用于任意数量的字符。

    DECLARE @str VARCHAR(100) = 'AB/1234/10'
    
    SELECT LEFT(@str, CHARINDEX('/', @str) - 1) AS Column1
        , SUBSTRING(@str, CHARINDEX('/', @str) + 1, CHARINDEX('/', SUBSTRING(@str, CHARINDEX('/', @str) + 1, LEN(@str))) - 1) AS Column2
        , RIGHT(@str, CHARINDEX('/', REVERSE(@str)) - 1) AS Column3
    

    【讨论】:

    • 如果我可以将多个答案标记为正确,我也会标记这个答案,它基本上与我标记为正确的答案相同,但我真的很欣赏它的稳健性。它更适用于一般用途。谢谢。
    猜你喜欢
    • 2017-05-06
    • 2016-07-22
    • 2021-06-23
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 2017-07-04
    相关资源
    最近更新 更多