我有以下字符串:
1119/2/483/11021
我想反转该字符串中元素的顺序。所需输出:
11021/483/2/1119
T-SQL 2014 版
SQL Server 2022+(或 Azure SQL DB/MI)
STRING_SPLIT
得到增强以支持返回序数位置,所以现在 我们可以这样做:
DECLARE @OriginalString varchar(max) = '1119/2/483/11021';
SELECT NewString = STRING_AGG(value, '/')
WITHIN GROUP (ORDER BY ordinal DESC)
FROM STRING_SPLIT(@OriginalString, '/', 1);
但是对于以前的版本...您需要一个有序的分割函数,例如(灵感)或者,如果你不喜欢这个,其他一些在这里:
CREATE FUNCTION dbo.SplitOrdered
(
@list nvarchar(max),
@delim nvarchar(10)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
WITH w(n) AS (SELECT 0 FROM (VALUES (0),(0),(0),(0)) w(n)),
k(n) AS (SELECT 0 FROM w a, w b),
r(n) AS (SELECT 0 FROM k a, k b, k c, k d, k e, k f, k g, k h),
p(n) AS (SELECT TOP (COALESCE(LEN(@list), 0))
ROW_NUMBER() OVER (ORDER BY @@SPID) -1 FROM r),
spots(p) AS
(
SELECT n FROM p
WHERE (SUBSTRING(@list, n, LEN(@delim + 'x') - 1) LIKE @delim OR n = 0)
),
parts(p,val) AS
(
SELECT p, SUBSTRING(@list, p + LEN(@delim + 'x') - 1,
LEAD(p, 1, 2147483647) OVER (ORDER BY p) - p - LEN(@delim))
FROM spots AS s
)
SELECT listpos = ROW_NUMBER() OVER (ORDER BY p),
Item = LTRIM(RTRIM(val))
FROM parts
);
然后您可以使用
STRING_AGG()
(如果是 SQL Server 2017 或更高版本)或 FOR XML PATH
(在较低版本上)重新组装:
SQL Server 2017/2019
DECLARE @OriginalString nvarchar(255) = N'1119/2/483/11021';
SELECT NewString = STRING_AGG(o.Item, N'/')
WITHIN GROUP (ORDER BY listpos DESC)
FROM dbo.SplitOrdered(@OriginalString, N'/') AS o;
SQL Server < 2017
DECLARE @OriginalString nvarchar(255) = N'1119/2/483/11021';
SELECT NewString = STUFF(
(SELECT N'/' + o.Item
FROM dbo.SplitOrdered(@OriginalString, N'/') AS o
ORDER BY o.listpos DESC
FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)'),1,1,N'');
请尝试以下基于内置
PARSENAME()
T-SQL 函数的解决方案。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Tokens VARCHAR(MAX));
INSERT INTO @tbl (Tokens) VALUES
('1119/2/483/11021'),
('1120/25/484/1102');
-- DDL and sample data population, end
SELECT tbl.*
, PARSENAME(c, 1) + '/' +
PARSENAME(c, 2) + '/' +
PARSENAME(c, 3) + '/' +
PARSENAME(c, 4) AS Result
FROM @tbl AS tbl
CROSS APPLY (VALUES (REPLACE(Tokens, '/', '.') )) AS t(c);
输出
+----+------------------+------------------+
| ID | Tokens | Result |
+----+------------------+------------------+
| 1 | 1119/2/483/11021 | 11021/483/2/1119 |
| 2 | 1120/25/484/1102 | 1102/484/25/1120 |
+----+------------------+------------------+
首先,拆分字符串并将其转换为列,然后按 desc 排序并将多行值显示到单行中。在下面的代码中,您可以设置任意字符串和分割字符。
尝试以下方法。
DECLARE @S varchar(max) ,
@Split char(1),
@X xml
DECLARE @Names VARCHAR(8000)
SELECT @S = '1119/2/483/11021',
@Split = '/'
SELECT @X = CONVERT(xml,' <root> <myvalue>' +
REPLACE(@S,@Split,'</myvalue> <myvalue>') + '</myvalue> </root> ')
select @Names = COALESCE(@Names + '/', '') + Value from (
select rowno,Value from (
select ROW_NUMBER() OVER(ORDER BY d) AS rowno , Value from (
SELECT T.c.value('.','varchar(20)') as Value,0 as d
FROM @X.nodes('/root/myvalue') T(c)
) m
) r
) t order by t.rowno desc
select @Names as ReverseString
将字符串拆分为子字符串,然后将它们重新连接起来,这很可能是一个好方法。
一些评论提到使用 string-reverse,但这在您的情况下似乎根本不是一个好方法,因为您只想反转当前字符串中的单词顺序,而不是实际上按字符反转整个文本字符串-角色。
PS:string_split不能保证块的顺序!