反转字符串中元素的顺序

问题描述 投票:0回答:4

我有以下字符串:

1119/2/483/11021

我想反转该字符串中元素的顺序。所需输出:

11021/483/2/1119

T-SQL 2014 版

sql sql-server t-sql sql-server-2014
4个回答
2
投票

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'');

0
投票

请尝试以下基于内置

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 |
+----+------------------+------------------+

0
投票

首先,拆分字符串并将其转换为列,然后按 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

-1
投票

将字符串拆分为子字符串,然后将它们重新连接起来,这很可能是一个好方法。

一些评论提到使用 string-reverse,但这在您的情况下似乎根本不是一个好方法,因为您只想反转当前字符串中的单词顺序,而不是实际上按字符反转整个文本字符串-角色。

PS:string_split不能保证块的顺序!

© www.soinside.com 2019 - 2024. All rights reserved.