alter FUNCTION FlipName(@input VARCHAR(250))
RETURNS VARCHAR(250)
AS BEGIN
DECLARE @i int ,@add varchar(255)
set @i=1
set @add=''
declare @work varchar(250)
set @work=''
WHILE @i <= len(@input)
BEGIN
declare @pivot varchar(255)
set @pivot=SUBSTRING(@input,@i,1)
while @pivot <>' '
begin
set @add=@add+@pivot
set @i=@i+1
set @pivot=SUBSTRING(@input,@i,1)
end
set @work=@add+' '+@work
set @add=''
SET @i = @i + 1
END
return @work
END
示例输入:我叫Jarvis
示例输出:Jarvis是我的名字
我正在寻找对此的更短,更简洁的替代代码,因为这里的嵌套循环是性能的杀手。
我正在寻找一种可能没有循环的更好的解决方法
请为您的解决方案提供一个简洁的说明,说明其效果如何。
提前谢谢
答案 0 :(得分:3)
T-SQL并不是字符串处理的最佳解决方案。但这完全可以做到没有循环(SQL Server 2017 +):
DECLARE @s NVARCHAR(MAX) = N'My name is Jarvis';
SELECT @s, STRING_AGG(value, ' ') WITHIN GROUP(ORDER BY rn DESC)
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY 1/0)AS rn
FROM STRING_SPLIT(REPLACE(@s, ' ', '.'), '.'))s;
答案 1 :(得分:2)
考虑到这里的序数位置很重要(STRING_SPLIT
不会返回),并且STRING_SPLIT
和STRING_AGG
是最近添加的函数,因此可以使用{{3} }和FOR XML PATH
。这意味着顺序得到保证(因为delimitedsplit8k
返回顺序位置),这意味着您不需要SQL Server 2017:
USE Sandbox;
GO
CREATE FUNCTION dbo.ReverseString_fn (@input varchar(255))
RETURNS table AS
RETURN
SELECT STUFF((SELECT ' ' + DS.Item
FROM dbo.DelimitedSplit8K(@input,' ') DS
ORDER BY DS.ItemNumber DESC
FOR XML PATH('')),1,1,'') AS ReverseString;
GO
WITH VTE AS (
SELECT 'My name is Jarvis' AS String)
SELECT *
FROM VTE V
CROSS APPLY dbo.ReverseString_fn(V.String) RS;
GO
DROP FUNCTION dbo.ReverseString_fn;
答案 2 :(得分:1)
还有另一种...以下方法是完全内联的,并结合XML通过位置获取元素的能力而使用了即时计数表:
DECLARE @input VARCHAR(100)='My name is Jarvis';
WITH Casted(inputXml) AS
(
SELECT CAST('<x>' + REPLACE((SELECT @input AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML)
)
,Tally(Nmbr) AS
(
SELECT TOP(SELECT inputXml.value('count(/x)','int') FROM Casted) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values
)
SELECT STUFF(
(
SELECT ' ' + c.inputXml.value('(/x[sql:column("t.Nmbr")]/text())[1]','varchar(100)')
FROM Tally t
CROSS JOIN Casted c
ORDER BY t.Nmbr DESC
FOR XML PATH(''),TYPE).value('.','varchar(max)'
),1,1,'');
答案 3 :(得分:0)
我不建议在后端这样做。 但是要解决( SQL Server 2016以下)的问题,您可以使用以下代码。 您可以使用以下代码创建函数,然后在表行上调用它。
DECLARE @VAL VARCHAR(MAX) ='My name is Jarvis', @NEW_VAL VARCHAR(MAX)='';
SELECT @VAL = '<M>'+ REPLACE(@VAL, ' ','</M><M>')+'</M>';
SELECT @NEW_VAL = @NEW_VAL+ ' ' + NEW_TEXT FROM (
SELECT ROW_NUMBER() OVER(ORDER BY(SELECT 1)) SNO,
splt.x.value('.','varchar(100)') NEW_TEXT FROM (
SELECT CAST(@VAL AS XML) AS DATA
)AS A
CROSS APPLY DATA.nodes('/M') as splt(x)
)B
ORDER BY SNO DESC;
SELECT @NEW_VAL
结果:
Jarvis is name My
答案 4 :(得分:-1)
如果您想逐个单词地反转字符串,则可以使用以下优化代码。
CREATE FUNCTION [dbo].[fn_ReverseWordsInSentence]
(
@ip VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
BEGIN
DECLARE @op VARCHAR(MAX)
SET @op = ''
DECLARE @Lenght INT
WHILE LEN(@ip) > 0
BEGIN
IF CHARINDEX(' ', @ip) > 0
BEGIN
SET @op = SUBSTRING(@ip,0,CHARINDEX(' ', @ip)) + ' ' + @op
SET @ip = LTRIM(RTRIM(SUBSTRING(@ip,CHARINDEX(' ', @ip) + 1,LEN(@ip))))
END
ELSE
BEGIN
SET @op = @ip + ' ' + @op
SET @ip = ''
END
END
RETURN @op
END
您可以使用您提到的输入字符串执行此功能,如下所示。
SELECT [dbo].[fn_ReverseWordsInSentence] ('My name is Jarvis')
这将返回以下字符串作为输出。
“贾维斯是我的名字”
如果只想逐个字符地反转整个字符串,则可以在内置的反向字符串函数中使用Sql Server。
DECLARE @test varchar(250) = 'My name is Jarvis'
SELECT reverse(@test)
这将返回“ sivraJ si eman yM”作为输出。