Select 列中的子字符串,但每条记录都有不同的模式
Select substring from column but each record has different pattern
我的每条记录都有不同字符串模式的列,我们称之为 [描述]。这是记录示例
[Description]
-qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532
-qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234
-qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A
我只想选择最后一个数字顺序 - 所以输出将是:
[Description]
-11000532
-11001234
-21001123
有什么函数怎么获取吗?
谢谢
您的示例很棘手,因为它也将字母作为订单号的一部分。
我假设您的数据类型是 VARCHAR(4000),因此,我在末尾应用了子字符串 4000,以使其最终更简单。
DECLARE @table table(Description varchar(4000))
insert into @table values
('-qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532')
,('-qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A')
,('-qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234');
SELECT SUBSTRING(REVERSE(SUBSTRING(REVERSE(Description),1,CHARINDEX('+',REVERSE(Description)))),PATINDEX('%[1-9]%',REVERSE(SUBSTRING(REVERSE(Description),1,CHARINDEX('+',REVERSE(Description))))),4000) as ordernumber FROM @table
ordernumber
11000532
21001123A
11001234
请尝试以下解决方案。
第一个解决方案适用于 SQL Server 2017 及更高版本。
它通过执行以下步骤来工作:
- 它正在将列值标记为 XML。
- 最后一个标记是我们的目标,即
(/root/r[last()]/text())[1]
- TRIM() 删除不需要的字符。
第二个解决方案适用于 SQL Server 2012。它涉及更多。
SQL 2017
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Tokens VARCHAR(4000));
INSERT INTO @tbl VALUES
('-qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532'),
('-qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A'),
('-qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = '+'
, @CharsToRemove VARCHAR(100) = 'AZ';
SELECT ID, tokens
, TRIM(@CharsToRemove FROM token) AS Result
FROM @tbl
CROSS APPLY (VALUES (TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML))) AS t(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(256)'))) AS t2(token);
SQL 2012
SELECT ID, tokens
, (
SELECT SUBSTRING(token, number, 1)
FROM @tbl AS c
CROSS APPLY (
SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 AND LEN(token)
) V
WHERE c.ID = p.ID
FOR XML PATH('r'), TYPE, ROOT('root')
)
.query('for $x in /root/r
return if (xs:int($x) instance of xs:int) then $x
else ()')
.query('/r/text()').value('.', 'BIGINT') AS Result
FROM @tbl AS p
CROSS APPLY (VALUES (TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML))) AS t(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(256)'))) AS t2(token);
输出
+----+---------------------------------------------------------------------+----------+
| ID | tokens | Result |
+----+---------------------------------------------------------------------+----------+
| 1 | -qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532 | 11000532 |
| 2 | -qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A | 21001123 |
| 3 | -qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234 | 11001234 |
+----+---------------------------------------------------------------------+----------+
我的每条记录都有不同字符串模式的列,我们称之为 [描述]。这是记录示例
[Description]
-qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532
-qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234
-qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A
我只想选择最后一个数字顺序 - 所以输出将是:
[Description]
-11000532
-11001234
-21001123
有什么函数怎么获取吗?
谢谢
您的示例很棘手,因为它也将字母作为订单号的一部分。
我假设您的数据类型是 VARCHAR(4000),因此,我在末尾应用了子字符串 4000,以使其最终更简单。
DECLARE @table table(Description varchar(4000))
insert into @table values
('-qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532')
,('-qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A')
,('-qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234');
SELECT SUBSTRING(REVERSE(SUBSTRING(REVERSE(Description),1,CHARINDEX('+',REVERSE(Description)))),PATINDEX('%[1-9]%',REVERSE(SUBSTRING(REVERSE(Description),1,CHARINDEX('+',REVERSE(Description))))),4000) as ordernumber FROM @table
ordernumber |
---|
11000532 |
21001123A |
11001234 |
请尝试以下解决方案。
第一个解决方案适用于 SQL Server 2017 及更高版本。
它通过执行以下步骤来工作:
- 它正在将列值标记为 XML。
- 最后一个标记是我们的目标,即
(/root/r[last()]/text())[1]
- TRIM() 删除不需要的字符。
第二个解决方案适用于 SQL Server 2012。它涉及更多。
SQL 2017
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Tokens VARCHAR(4000));
INSERT INTO @tbl VALUES
('-qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532'),
('-qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A'),
('-qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = '+'
, @CharsToRemove VARCHAR(100) = 'AZ';
SELECT ID, tokens
, TRIM(@CharsToRemove FROM token) AS Result
FROM @tbl
CROSS APPLY (VALUES (TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML))) AS t(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(256)'))) AS t2(token);
SQL 2012
SELECT ID, tokens
, (
SELECT SUBSTRING(token, number, 1)
FROM @tbl AS c
CROSS APPLY (
SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 AND LEN(token)
) V
WHERE c.ID = p.ID
FOR XML PATH('r'), TYPE, ROOT('root')
)
.query('for $x in /root/r
return if (xs:int($x) instance of xs:int) then $x
else ()')
.query('/r/text()').value('.', 'BIGINT') AS Result
FROM @tbl AS p
CROSS APPLY (VALUES (TRY_CAST('<root><r><![CDATA[' +
REPLACE(tokens, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML))) AS t(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(256)'))) AS t2(token);
输出
+----+---------------------------------------------------------------------+----------+
| ID | tokens | Result |
+----+---------------------------------------------------------------------+----------+
| 1 | -qwetw MANN/1234556/DATE/030621/B/C/ACC/DIFF+AA11000532 | 11000532 |
| 2 | -qwert 123456789101213/-/BACK/300621/Rekening/Tutup+06+ZZZ21001123A | 21001123 |
| 3 | -qwerty 123456789/06/29/2021/ACC./DONE/CLOSED+06+AA11001234 | 11001234 |
+----+---------------------------------------------------------------------+----------+