如何按字母顺序对字符串进行排序

8

我是SQL Server和Stack Overflow的新手,请原谅我的错误。

在一列中按字母顺序排序一个值是否可能?这是我的表格:

NAME
......
XZYVW
EBACD

我的结果应该像下面这样。
NAME
......
VWXYZ
ABCDE 

有什么办法可以得到这个?

1
这篇文章可能会对您有所帮助,http://www.techrepublic.com/blog/the-enterprise-cloud/sorting-character-strings-using-sql-server/ - Daniel E.
我必须为此编写一个函数吗?难道没有像.Net中那样的内置功能吗?@Daniel E. - user4344765
1
@MohithKm:不,你要么必须自己编写一个T-SQL函数,要么使用.NET方法(你也可以在SQL-Server中使用.NET),或者重构数据库设计。最简单的方法是使用.NET在客户端对其进行排序以便在显示时进行展示。 - Tim Schmelter
1
每当我看到这样的东西,我就不禁想知道一个交叉点中是否有多个值(这违反了第一范式),或者这只是一个课堂作业。在现实世界中,这种情况确实是一个真正的挑战。 - Sean Lange
1
被投票选中的答案将会是非常低效的表现(WHILE循环,标量函数...)。t-clausen.dk的答案更好,但在执行时会使用太多行。你可能想要在这里阅读一下... - Shnugo
4个回答

5

即使有一些优化的可能性。这里有两个函数使用冒泡排序来排序字符。

CREATE FUNCTION udf_SortString
(
    @string VARCHAR(1000)
)
RETURNS VARCHAR(1000)
AS
BEGIN
    DECLARE @len TINYINT
    DECLARE @i TINYINT
    DECLARE @currentchar CHAR(1)
    DECLARE @swapped BIT
    DECLARE @begin BIT
    DECLARE @nextchar CHAR(1)

    SET @begin = 1
    SET @len = LEN(@string)
    SET @i = 1

    WHILE @begin = 1 OR @swapped = 1
    BEGIN
        SET @swapped = 0
        SET @i = 1
        SET @begin = 0
        WHILE @i <= @len
        BEGIN
            SET @currentchar = SUBSTRING(@string, @i, 1)
            SET @nextchar = SUBSTRING(@string, @i + 1, 1)

            IF @currentchar > @nextchar AND (@nextchar > '')
            BEGIN
                SET @string = dbo.udf_swap(@string, @i, @i + 1)
                SET @swapped = 1
            END

            SET @i = @i + 1
        END
    END

    RETURN(@string)
END

功能 2:

CREATE FUNCTION dbo.udf_Swap
(
    @fullstring VARCHAR(1000),
    @charlocation1 TINYINT,
    @charlocation2 TINYINT
)
RETURNS VARCHAR(1000)
AS
BEGIN
        DECLARE @returnval varchar(1000)
        DECLARE @begin VARCHAR(1000), @middle VARCHAR(1000), @end VARCHAR(1000)
        DECLARE @firstchar CHAR(1), @secondchar CHAR(1), @len INT
        SET @fullstring = LTRIM(RTRIM(@fullstring))
        SET @len = LEN(@fullstring)

    IF @charlocation1 > @len OR @charlocation2 > @len
        SET @returnval = @fullstring
        ELSE
        BEGIN
               SET @firstchar = SUBSTRING(@fullstring, @charlocation1, 1)
               SET @secondchar = SUBSTRING(@fullstring, @charlocation2, 1)
               SET @begin = LEFT(@fullstring, (@charlocation1-1))
               SET @middle = SUBSTRING(@fullstring, @charlocation1+1, (@charlocation2-@charlocation1)-1)
               SET @end = SUBSTRING(@fullstring, @charlocation2+1, @len)
               SET @returnval = @begin + @secondchar + @middle + @firstchar + @end
        END
    RETURN(@returnval)
END

结果:

select dbo.udf_SortString('zxcvbfgrtyuijklm')
--Returns bcfgijklmrtuvxyz

--Reference

--Quick demo here


这将会非常慢... 如果您有兴趣,您可能想要阅读我在问题下面的评论... - Shnugo

5

这将按字母顺序排序,而不使用函数。在@Shnugo的评论后进行了优化重写。

DECLARE @t table(col varchar(4000))
INSERT @t values('kdjfh'),('zug')

SELECT
  Col, 
  (
    SELECT
      chr
    FROM
      (SELECT TOP(LEN(Col)) 
         SUBSTRING(Col,ROW_NUMBER() OVER(ORDER BY 1/0),1)
       FROM sys.messages) A(Chr)
       ORDER by chr
       FOR XML PATH(''), type).value('.', 'varchar(max)'
      ) SortedCol
FROM
  @t

结果:

col    SortedCol
kdjfh  dfhjk
zug    guz

嗨,这将在任何执行中使用太多行... 你可能想要阅读这个答案。在那里,我提供了一种方法来限制实际行数与每个字符串的实际字符数相同。但是我会给你+1,因为这比其他答案好多了;-) - Shnugo
@Shnugo 进行了优化和重写。 - t-clausen.dk

2
创建一个用户定义标量函数。
CREATE FUNCTION dbo.Alphaorder (@str VARCHAR(50))
returns VARCHAR(50)
  BEGIN
      DECLARE @len    INT,
              @cnt    INT =1,
              @str1   VARCHAR(50)='',
              @output VARCHAR(50)=''

      SELECT @len = Len(@str)
      WHILE @cnt <= @len
        BEGIN
            SELECT @str1 += Substring(@str, @cnt, 1) + ','

            SET @cnt+=1
        END

      SELECT @str1 = LEFT(@str1, Len(@str1) - 1)

      SELECT @output += Sp_data
      FROM  (SELECT Split.a.value('.', 'VARCHAR(100)') Sp_data
             FROM   (SELECT Cast ('<M>' + Replace(@str1, ',', '</M><M>') + '</M>' AS XML) AS Data) AS A
                    CROSS APPLY Data.nodes ('/M') AS Split(a)) A
      ORDER  BY Sp_data

      RETURN @output
  END

结果:

SELECT dbo.Alphaorder ('XZYVW') --VWXYZ

1
这将会非常慢... 如果您有兴趣,您可能想要阅读我在问题下面的评论... - Shnugo

-1

不是mssql,但在Presto中我找到了这种方法。也许有人可以转换它,或者找到更好的方法来将字符串拆分为数组,排序并重新连接:

SELECT ARRAY_JOIN(ARRAY_SORT(REGEXP_EXTRACT_ALL('aaffed', '.')), '') --> 'aadeff'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接