我有一个字母数字字符串作为输入,我想从中得到两个结果:
删除所有数字的字符串
和
一个整数,它是输入字符串中所有数字的总和。
例如,对于这个输入:
GR35hc7vdH35
Run Code Online (Sandbox Code Playgroud)
我想要以下输出:
| Col1. | Col2 |
----------------------------------
| GRhcvdH | 23 |
Run Code Online (Sandbox Code Playgroud)
怎么能做到这一点?
SQL Server 不支持替换多个字符的模式 - 所以通过它REPLACE
可能需要 10 个操作。
考虑到这一点,一种方法是使用递归 CTE 顺序处理数字 0-9。
它进行替换,然后检查前后字符串的长度,以了解该数字有多少个字符以及需要添加到总数中的内容。
DECLARE @Input VARCHAR(8000) = 'GR35hc7vdH35';
WITH R(Level,Input,Accumulator,StringLength)
AS (SELECT 0,
Input,
0,
DATALENGTH(Input)
FROM (SELECT REPLACE(@Input, '0', '')) D(Input)
UNION ALL
SELECT NewLevel,
NewInput,
Accumulator + NewLevel * ( StringLength - NewStringLength ),
NewStringLength
FROM R
CROSS APPLY (SELECT Level + 1) C(NewLevel)
CROSS APPLY (SELECT REPLACE(Input, NewLevel, '')) C2(NewInput)
CROSS APPLY (SELECT DATALENGTH(NewInput)) C3(NewStringLength)
WHERE NewLevel <= 9)
SELECT Input AS Col1,
Accumulator AS Col2
FROM R
WHERE Level = 9;
Run Code Online (Sandbox Code Playgroud)
或者您可以使用 CLR 和正则表达式(SQL Server 2012 兼容版本)。
DECLARE @Input VARCHAR(8000) = 'GR35hc7vdH35';
WITH R(Level,Input,Accumulator,StringLength)
AS (SELECT 0,
Input,
0,
DATALENGTH(Input)
FROM (SELECT REPLACE(@Input, '0', '')) D(Input)
UNION ALL
SELECT NewLevel,
NewInput,
Accumulator + NewLevel * ( StringLength - NewStringLength ),
NewStringLength
FROM R
CROSS APPLY (SELECT Level + 1) C(NewLevel)
CROSS APPLY (SELECT REPLACE(Input, NewLevel, '')) C2(NewInput)
CROSS APPLY (SELECT DATALENGTH(NewInput)) C3(NewStringLength)
WHERE NewLevel <= 9)
SELECT Input AS Col1,
Accumulator AS Col2
FROM R
WHERE Level = 9;
Run Code Online (Sandbox Code Playgroud)
示例用法
SELECT Stripped,
Total
FROM [dbo].[ReplaceAndTotalise]('GR35hc7vdH35')
Run Code Online (Sandbox Code Playgroud)
请尝试以下操作:
CREATE FUNCTION dbo.AlphaNumericSplitter
(
@string varchar(8000)
)
RETURNS TABLE
AS
RETURN (
WITH Alphanumeric (col1)
AS (
-- Put out string into a cte table
SELECT @string
),
Nmbrs (n)
AS (
-- Numbers so we can split the string
SELECT TOP(LEN(@string))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM sys.all_objects AS o1
CROSS
JOIN sys.all_objects AS o2
),
y
AS (
SELECT N.n
a.col1,
N.x,
-- Get the numbers only
Numbers = TRY_CONVERT(int, N.x)
FROM Alphanumeric AS a
CROSS
APPLY (SELECT [x] = SUBSTRING(a.col1, n, 1), Nmbrs.n FROM Nmbrs) AS N
)
SELECT z.Col1,
Col2 = SUM(y.Numbers)
FROM y
-- Get the letters only
CROSS
APPLY (SELECT (SELECT x + '' FROM y WHERE Numbers IS NULL ORDER BY y.n FOR XML PATH(''))) AS z (Col1)
GROUP BY
z.Col1);
GO
SELECT * FROM AlphaNumericSplitter('GR35hc7vdH35');
Run Code Online (Sandbox Code Playgroud)
结果: