【问题标题】: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 |
【问题讨论】:
-
-
提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。
-
标签:
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
【解决方案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 用法。