使用 T-SQL,我试图找到最简单的方法来反转字符串中的数字。Test123Hello
所以对于像have这样的字符串Test321Hello
。
[Before] [After]
Test123Hello Test321Hello
Tt143 Hello Tt341 Hello
12Hll 21Hll
Tt123H3451end Tt321H1543end
使用 T-SQL,我试图找到最简单的方法来反转字符串中的数字。Test123Hello
所以对于像have这样的字符串Test321Hello
。
[Before] [After]
Test123Hello Test321Hello
Tt143 Hello Tt341 Hello
12Hll 21Hll
Tt123H3451end Tt321H1543end
你可以使用这个功能
CREATE FUNCTION [dbo].[fn_ReverseDigit_MA]
(
@Str_IN nVARCHAR(max)
)
RETURNS NVARCHAR(max)
AS
BEGIN
DECLARE @lenstr AS INT =LEN(@Str_IN)
DECLARE @lastdigend AS INT=0
while (@lastdigend<@lenstr)
BEGIN
DECLARE @strPart1 AS NVARCHAR(MAX)=LEFT(@Str_IN,@lastdigend)
declare @lenstrPart1 AS INT=LEN(@strPart1)
DECLARE @strPart2 AS NVARCHAR(MAX)=RIGHT(@Str_IN,@lenstr-@lastdigend)
declare @digidx as int=patindex(N'%[0-9]%' ,@strPart2)+@lenstrPart1
IF(@digidx=@lenstrPart1)
BEGIN
BREAK;
END
DECLARE @strStartdig AS NVARCHAR(MAX) = RIGHT(@Str_IN,@lenstr-@digidx+1)
declare @NDidx as int=patindex(N'%[^0-9]%' ,@strStartdig)+@digidx-1
IF(@NDidx<=@digidx)
BEGIN
SET @NDidx=@lenstr+1
END
DECLARE @strRet AS NVARCHAR(MAX)=LEFT(@Str_IN,@digidx-1) +REVERSE(SUBSTRING(@Str_IN,@digidx,@NDidx-@digidx)) +RIGHT(@Str_IN,@lenstr-@NDidx+1)
SET @Str_IN=@strRet
SET @lastdigend=@NDidx-1
END
return @Str_IN
END
只需使用PATINDEX
for 搜索,逐部分附加到结果字符串:
CREATE FUNCTION [dbo].[fn_ReverseDigits]
(
@Value nvarchar(max)
)
RETURNS NVARCHAR(max)
AS
BEGIN
IF @Value IS NULL
RETURN NULL
DECLARE
@TextIndex int = PATINDEX('%[^0-9]%', @Value),
@NumIndex int = PATINDEX('%[0-9]%', @Value),
@ResultValue nvarchar(max) = ''
WHILE LEN(@ResultValue) < LEN(@Value)
BEGIN
-- Set the index to end of the string if the index is 0
SELECT @TextIndex = CASE WHEN @TextIndex = 0 THEN LEN(@Value) + 1 ELSE LEN(@ResultValue) + @TextIndex END
SELECT @NumIndex = CASE WHEN @NumIndex = 0 THEN LEN(@Value) + 1 ELSE LEN(@ResultValue) + @NumIndex END
IF @NumIndex < @TextIndex
SELECT @ResultValue = @ResultValue + REVERSE(SUBSTRING(@Value, @NumIndex, @TextIndex -@NumIndex))
ELSE
SELECT @ResultValue = @ResultValue + (SUBSTRING(@Value, @TextIndex, @NumIndex - @TextIndex))
-- Update index variables
SELECT
@TextIndex = PATINDEX('%[^0-9]%', SUBSTRING(@Value, LEN(@ResultValue) + 1, LEN(@Value) - LEN(@ResultValue))),
@NumIndex = PATINDEX('%[0-9]%', SUBSTRING(@Value, LEN(@ResultValue) + 1, LEN(@Value) - LEN(@ResultValue)))
END
RETURN @ResultValue
END
测试 SQL
declare @Values table (Value varchar(20))
INSERT @Values VALUES
('Test123Hello'),
('Tt143 Hello'),
('12Hll'),
('Tt123H3451end'),
(''),
(NULL)
SELECT Value, dbo.fn_ReverseDigits(Value) ReversedValue FROM @Values
结果
Value ReversedValue
-------------------- --------------------
Test123Hello Test321Hello
Tt143 Hello Tt341 Hello
12Hll 21Hll
Tt123H3451end Tt321H1543end
NULL NULL
希望这有帮助:
declare @s nvarchar(128) ='Test321Hello'
declare @numStart as int, @numEnd as int
select @numStart =patindex('%[0-9]%',@s)
select @numEnd=len(@s)-patindex('%[0-9]%',REVERSE(@s))
select
SUBSTRING(@s,0,@numstart)+
reverse(SUBSTRING(@s,@numstart,@numend-@numstart+2))+
SUBSTRING(@s,@numend+2,len(@s)-@numend)
使用此功能它也将处理多次出现的数字
create FUNCTION [dbo].[GetReverseNumberFromString] (@String VARCHAR(2000))
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE @Count INT
DECLARE @IntNumbers VARCHAR(1000)
declare @returnstring varchar(max)=@String;
SET @Count = 0
SET @IntNumbers = ''
WHILE @Count <= LEN(@String)
BEGIN
IF SUBSTRING(@String, @Count, 1) >= '0'
AND SUBSTRING(@String, @Count, 1) <= '9'
BEGIN
SET @IntNumbers = @IntNumbers + SUBSTRING(@String, @Count, 1)
END
IF (
SUBSTRING(@String, @Count + 1, 1) < '0'
OR SUBSTRING(@String, @Count + 1, 1) > '9'
)
AND SUBSTRING(@String, @Count, 1) >= '0'
AND SUBSTRING(@String, @Count, 1) <= '9'
BEGIN
SET @IntNumbers = @IntNumbers + ','
END
SET @Count = @Count + 1
END
declare @RevStrings table (itemz varchar(50))
INSERT INTO @RevStrings(itemz)
select items from dbo.Split(@IntNumbers,',')
select @returnstring = Replace(@returnstring, itemz,REVERSE(itemz))from @RevStrings
RETURN @returnstring
END
您的示例字符串
select [dbo].[GetReverseNumberFromString]('Tt123H3451end')
结果
Tt321H1543end
更新 :
如果您没有拆分功能,则首先创建它,我已将其包含在下面
create FUNCTION Split
(
@Input NVARCHAR(MAX),
@Character CHAR(1)
)
RETURNS @Output TABLE (
Items NVARCHAR(1000)
)
AS
BEGIN
DECLARE @StartIndex INT, @EndIndex INT
SET @StartIndex = 1
IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
BEGIN
SET @Input = @Input + @Character
END
WHILE CHARINDEX(@Character, @Input) > 0
BEGIN
SET @EndIndex = CHARINDEX(@Character, @Input)
INSERT INTO @Output(Items)
SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)
SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
END
RETURN
END
GO
这是一种基于集合的方法:
;WITH Tally (n) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
), UnpivotCTE AS (
SELECT id, x.c, n, y.isNumber,
n - ROW_NUMBER() OVER (PARTITION BY id, y.isNumber
ORDER BY n) AS grp
FROM mytable
CROSS JOIN Tally
CROSS APPLY (SELECT SUBSTRING(col, n, 1)) AS x(c)
CROSS APPLY (SELECT ISNUMERIC(x.c)) AS y(isNumber)
WHERE n <= LEN(col)
), ToConcatCTE AS (
SELECT id, c, n, isNumber,
grp + MIN(n) OVER (PARTITION BY id, isNumber, grp) AS grpAsc
FROM UnpivotCTE
)
SELECT id, col,
REPLACE(
(SELECT c AS [text()]
FROM ToConcatCTE AS t
WHERE t.id = m.id
ORDER BY id,
grpAsc,
CASE WHEN isNumber = 0 THEN n END,
CASE WHEN isNumber = 1 THEN n END DESC
FOR XML PATH('')), ' ',' ') AS col2
FROM mytable AS m
使用计数表来“反透视”字符串的所有字符。然后ROW_NUMBER
用于识别数字和非数字字符的孤岛。最后,FOR XML PATH
用于重建数字岛颠倒的初始字符串:ORDER BY
用于对数字字符岛进行倒序排序。
这将执行您要求的特定字符串:
select
substring('Test123Hello',1,4)
+
reverse(substring('Test123Hello',5,3))
+
substring('Test123Hello',8,5)
从其余的值来看,您似乎需要为您获得的任何字母数字模式制作模板。例如,您可以将上述内容应用于任何具有以下形状的值:
select * from [B&A] where [before] like '[a-z][a-z][a-z][a-z][0-9][0-9][0-9]
[a-z][a-z][a-z][a-z][a-z]'
换句话说,如果您将值(之前和之后)放入表 [B&A] 并调用列“之前”和“之后”,然后运行以下命令:
select
substring(before,1,4)
+
reverse(substring(before,5,3))
+
substring(before,8,5) as [after]
from [B&A] where [before] like '[a-z][a-z][a-z][a-z][0-9][0-9][0-9][a-z]
[a-z][a-z][a-z][a-z]'
然后它会给你'Test321Hello'。
但是,除非您为每个字母数字形状创建类似的“[0-9][az]”类型模板并将其应用于 [B&A] 表,否则其他 3 行不会受到影响。您必须将结果选择到临时表或另一个表中。
通过依次应用每个模板,您将获得大部分模板,然后您必须查看有多少行不受影响并检查字母数字形状并制作更多模板。最终你有一组代码,如果你运行它,它将捕获所有可能的组合。
您可以坐下来以这种方式设计一个代码,该代码捕获 [az] 和 [0-9] 的所有可能组合。很大程度上取决于您要处理的最大字符数。