我想知道如何(如果可能的话)颠倒从TSQL字符串(varchar)返回的单词的顺序。
我知道TSQL REVERSE
函数,但也会反转单词中的字母,例如:
输入> We want to tell you we all love StackOverflow
输出> wolfrevOkcatS evol lla ew uoy llet ot tnaw eW
我想在TSQL中实际实现以下目标:
输入> We want to tell you we all love StackOverflow
输出> Stackoverflow love all we you tell to want We
我在任何地方找到的唯一稍微类似的问题是this one,但是这包括拆分逗号分隔的字符串,我不需要这样做。
我确信有一种方法可以实现上述目标,即使它是自定义函数或SQL-CLR函数,也会非常感谢任何帮助。
修改
我设法使用以下内容拆分我的字符串:
-- Create a space delimited string for testing
declare @str varchar(max)
select @str = 'We want to tell you we all love StackOverflow'
-- XML tag the string by replacing spaces with </x><x> tags
declare @xml xml
select @xml = cast('<x><![CDATA['+ replace(@str,' ',']]></x><x><![CDATA[') + ']]></x>' as xml)
-- Finally select values from nodes <x> and trim at the same time
select ltrim(rtrim(mynode.value('.[1]', 'nvarchar(50)'))) as Code
from (select @xml doc) xx
cross apply doc.nodes('/x') (mynode)
现在的问题是尝试将它们全部重新组合成一个按向后(DESC)顺序排列的字符串。
答案 0 :(得分:6)
您可以在SQL中创建一个小函数来反转字符串,如下所示:
DECLARE @source VARCHAR(MAX)
DECLARE @dest VARCHAR(MAX)
DECLARE @lenght INT
SET @source = 'We want to tell you we all love StackOverflow'
SET @dest = ''
WHILE LEN(@source) > 0
BEGIN
IF CHARINDEX(' ', @source) > 0
BEGIN
SET @dest = SUBSTRING(@source,0,CHARINDEX(' ', @source)) + ' ' + @dest
SET @source = LTRIM(RTRIM(SUBSTRING(@source,CHARINDEX(' ', @source)+1,LEN(@source))))
END
ELSE
BEGIN
SET @dest = @source + ' ' + @dest
SET @source = ''
END
END
SELECT @dest
答案 1 :(得分:2)
首先,这是基于CLR的解决方案会更好的情况之一,特别是在性能方面(解决方案将不变地使用迭代和字符串操作)。
这里有几行C#可以实现结果,虽然它没有您需要的SQL-CLR代码:
string original = "We want to tell you we all love StackOverflow";
string[] parts = original.Split(' ');
StringBuilder reversedString = new StringBuilder();
for (int i = parts.Length - 1; i >= 0; i--)
{
reversedString.Append(parts[i]);
reversedString.Append(" ");
}
string result = reversedString.ToString();
LINQ会更短,但我想我会保持简单。对于T-SQL解决方案,您可以从已经提到的split post中的vzczc帖子中的splitString
函数开始。
基于此,你这样做:
DECLARE @ReverseString VARCHAR(MAX)
SET @ReverseString = ''
SELECT @ReverseString = @ReverseString + s + ' '
FROM
(
SELECT s, zeroBasedOccurance
FROM dbo.SplitString('We want to tell you we all love StackOverflow', ' ')
) A
ORDER BY A.zeroBasedOccurance DESC
SELECT @ReverseString
这应该可行,但它用于将字符串连接在一起的方法没有记录,在SQL Server的未来版本中可能无法正常工作。与CLR解决方案相比,它可能也会表现得非常糟糕,所以如果你有时间实现它,那就这样做。
答案 2 :(得分:2)
declare @str varchar(100),
@result varchar(100)
set @str = 'We want to tell you we all love StackOverflow'
;with cte as
(
select 1 pos_from, charindex(' ', @str) + 1 pos_to
union all
select pos_to, charindex(' ', @str + ' ', pos_to) + 1
from cte
where pos_to <= len(@str)
)
select @result = coalesce( @result + ' ', '') +substring(@str, pos_from, pos_to - pos_from - 1)
from cte
order by pos_to desc
select @result
答案 3 :(得分:1)
SQL Server的原生XML支持为这些问题提供了一些强大(简洁)的解决方案:
DECLARE @xml XML, @source VARCHAR(MAX), @delimiter VARCHAR(10)
SET @source = 'We want to tell you we all love StackOverflow'
SET @delimiter = ' '
SET @xml = CAST(('<X>' + REPLACE(@source, @delimiter, '</X><X>') + '</X>') AS XML)
SELECT STUFF((SELECT @delimiter + C.value('.', 'VARCHAR(50)')
FROM @xml.nodes('X') AS X(C)
ORDER BY ROW_NUMBER() OVER (ORDER BY (SELECT 0)) DESC
FOR XML PATH('')), 1, 1, '')
答案 4 :(得分:1)
Since the accepted answer is not a function, here is one.
Also I removed the extra useless space generated by the accepted answer
CREATE FUNCTION [dbo].[fn_ReverseWords] (@input VARCHAR(MAX))
RETURNS VARCHAR(MAX)
BEGIN
DECLARE @output VARCHAR(MAX)
SET @output = ''
WHILE LEN(@input) > 0
BEGIN
IF CHARINDEX(' ', @input) > 0
BEGIN
SET @output = SUBSTRING(@input,0,CHARINDEX(' ', @input)) + ' ' + @output
SET @input = LTRIM(RTRIM(SUBSTRING(@input,CHARINDEX(' ', @input) + 1,LEN(@input))))
END
ELSE
BEGIN
SET @output = @input + ' ' + @output
SET @input = ''
END
END
RETURN substring(@output,0, len(@output)) -- remove useless space
END