【问题标题】:Multi-character delimiter with STRING_SPLIT带有 STRING_SPLIT 的多字符分隔符
【发布时间】:2022-01-26 17:02:11
【问题描述】:

我想根据多个值(例如 !% 运算符)拆分值,但 STRING_SPLIT 只允许使用 1 个字符的分隔符。

我的字符串是这样的:

99001316 - ABCD 250 ML!%!%99001234 - CDEF 500 ML!%!%99001995 - OWEW 50 ML

我想要的是将数字和文本值分开。 当我这样做时:

SELECT value FROM STRING_SPLIT(@x, '%',1)

我来了

value
99001234 - ABCD 250 ML!
!
99001230 - CDEF 500 ML!
!
99001995 - OWEW 50 ML

而我想要的是

value string
99001234 ABCD 250 ML!
99001230 CDEF 500 ML!
99001995 OWEW 50 ML

【问题讨论】:

标签: sql-server tsql split delimiter


【解决方案1】:

一种选择是通过 JSON 解析字符串。你可能会注意到'!%!%'的分隔符

Declare @X varchar(max) = '99001316 - ABCD 250 ML!%!%99001230 - CDEF 500 ML!%!%99001395 - OWEW 50 ML'


Select Value  = rtrim(left(value,charindex('-',Value+'-')-1))
      ,String = ltrim(substring(value,charindex('-',Value+'-')+1,len(Value)))
 From  OpenJSON( '["'+replace(string_escape(@X,'json'),'!%!%','","')+'"]' )

结果

Value       String
99001316    ABCD 250 ML
99001230    CDEF 500 ML
99001395    OWEW 50 ML

【讨论】:

  • 非常感谢@John!
【解决方案2】:

另一种方法。

SQL

DECLARE @tokens NVARCHAR(max) = N'99001316 - ABCD 250 ML!%!%99001234 - CDEF 500 ML!%!%99001995 - OWEW 50 ML';

WITH rs AS
(
    SELECT value AS token 
    FROM STRING_SPLIT(REPLACE(@tokens,'!%!%','%') , '%')
)
SELECT * 
, LEFT(token, pos - 1) AS [value]
, RIGHT(token, LEN(token) - pos - 1) AS [string]
FROM rs
    CROSS APPLY (SELECT CHARINDEX('-', token)) AS t(pos);

输出

+------------------------+-----+-----------+-------------+
|         token          | pos |   value   |   string    |
+------------------------+-----+-----------+-------------+
| 99001316 - ABCD 250 ML |  10 | 99001316  | ABCD 250 ML |
| 99001234 - CDEF 500 ML |  10 | 99001234  | CDEF 500 ML |
| 99001995 - OWEW 50 ML  |  10 | 99001995  | OWEW 50 ML  |
+------------------------+-----+-----------+-------------+

【讨论】:

    【解决方案3】:

    这里还有一些想法

    DECLARE @X VARCHAR(MAX) = '99001316 - ABCD 250 ML!%!%99001230 - CDEF 500 ML!%!%99001395 - OWEW 50 ML';
    
    WITH s1 AS  (
                SELECT      ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ord1
                            , s1.value
                FROM        STRING_SPLIT(REPLACE(@X, '!%!%', '|'), '|') s1
                ),
    s2 AS       (
                SELECT      s1.ord1
                            , ROW_NUMBER() OVER (PARTITION BY s1.ord1 ORDER BY (SELECT 1)) AS ord2
                            , s2.value
                FROM        s1
                CROSS APPLY STRING_SPLIT(REPLACE(s1.value, ' - ', '|'), '|') s2
                )
    SELECT      MAX(CASE WHEN s2.ord2 = 1 THEN s2.value END) AS id
                , MAX(CASE WHEN s2.ord2 = 2 THEN s2.value END) AS text
    FROM        s2
    GROUP BY    s2.ord1
    

    您可以在 Azure 上包含 ordinal 列和 STRING_SPLIT(在第三个参数中传递 1)并删除上面两个 ord 列的 ROW_NUMBER 用法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-15
      • 2015-10-13
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      • 2014-07-08
      • 1970-01-01
      相关资源
      最近更新 更多