【问题标题】:How to sort a varchar datatype column by its numbers in SQL Server如何在 SQL Server 中按其编号对 varchar 数据类型列进行排序
【发布时间】:2015-05-24 16:58:58
【问题描述】:

我在 SQL Server 中有一个包含如下数据的列:

1.1.1.QuestionText
1.1.1.Question
1.1.1(a).Questions
1.1.2.Questionswithtext
1.1.2(b).Text
10.1.1.Answers
2.1.1.Questions
2.2.2.QuestionText

如何按升序显示?

【问题讨论】:

  • 如果我理解您,您是在尝试对数据的文本部分进行排序?忽略数字?这些值都在一个字段中吗?
  • @paqogomez - 我必须对所有值(数字和文本)进行排序,比如要排序的第一个数字,然后是字符。

标签: sql sql-server sql-order-by


【解决方案1】:

这应该可行:

SELECT  name
FROM    ( SELECT    name, SUBSTRING(name, 1,
                              LEN(name) - PATINDEX('%[0-9]%', REVERSE(name)) + 1) n
          FROM      #tmp
        ) v
ORDER BY CAST(PARSENAME(n, 4) AS INT),
         CAST(PARSENAME(n, 3) AS INT),
         CAST(PARSENAME(n, 2) AS INT),
         CAST(PARSENAME(n, 1) AS INT)

输出:

name
1.1.1.QuestionText
1.1.1.Question
1.1.1(a).Questions
1.1.2.Questionswithtext
1.1.2(b).Text
2.1.1.Questions
2.2.2.QuestionText
10.1.1.Answers

如果您想在版本号之后按文本订购,那么这将起作用:

SELECT  name
FROM    ( SELECT    name, SUBSTRING(name, 1,
                              LEN(name) - PATINDEX('%[0-9]%', REVERSE(name)) + 1) nv,
                          SUBSTRING(name, LEN(name) - PATINDEX('%[0-9]%', REVERSE(name)) + 2, 
                              LEN(name)) nt                            
          FROM      #tmp
        ) v
ORDER BY CAST(PARSENAME(nv, 4) AS INT),
         CAST(PARSENAME(nv, 3) AS INT),
         CAST(PARSENAME(nv, 2) AS INT),
         CAST(PARSENAME(nv, 1) AS INT),
         nt  

输出:

name
1.1.1(a).Questions
1.1.1.Question
1.1.1.QuestionText
1.1.2(b).Text
1.1.2.Questionswithtext
2.1.1.Questions
2.2.2.QuestionText
10.1.1.Answers

【讨论】:

  • 我认为你的输出应该是不同的1.1.1.QuestionText 会在1.1.1(a).Questions 之后出现;)。
  • 可能在其他机器上会有所不同。我只按版本号而不是后面的文本来订购。
【解决方案2】:

碰巧有一个四部分的命名,所以你可以使用parsename()。结果是这样的:

order by (case when isnumeric(arsename(col, 4)) = 1 then cast(parsename(col, 4) as int)
          end),
         (case when isnumeric(parsename(col, 3)) = 1 then cast(parsename(col, 3) as int)
          end),
         (case when isnumeric(parsename(col, 2)) = 1 then cast(parsename(col, 2) as int)
          end),
         (case when isnumeric(parsename(col, 1)) = 1 then cast(parsename(col, 1) as int)
          end),
         col

这并不完美,因为您似乎奇怪地放置了括号。但这对于您的目的可能已经足够了。

【讨论】:

  • 也许我错过了什么,但是this produces a syntax error
  • 不错!我喜欢使用Parsename(),尽管我认为它值得一个指向 MSDN 的链接。我已经编辑了你的答案以包含它,希望你不介意。
【解决方案3】:

试试这个:

        CREATE TABLE #TMP
        (
         name nvarchar(30)
        )

        INSERT INTO #TMP (name) VALUES ('1.1.1.QuestionText')
        INSERT INTO #TMP (name) VALUES ('1.1.1.Question')
        INSERT INTO #TMP (name) VALUES ('1.1.1(a).Questions')
        INSERT INTO #TMP (name) VALUES ('1.1.2.Questionswithtext')
        INSERT INTO #TMP (name) VALUES ('1.1.2(b).Text')
        INSERT INTO #TMP (name) VALUES ('10.1.1.Answers')
        INSERT INTO #TMP (name) VALUES ('2.1.1.Questions')
        INSERT INTO #TMP (name) VALUES ('2.2.2.QuestionText')

        select
        SUBSTRING(replace(name, '.',''),1,
                PATINDEX('%[^0-9]%',  
                    replace(name, '.','')
                ) -1
            ) as replaced, name from #TMP order by 
        CAST( 
            SUBSTRING(replace(name, '.',''),1,
                PATINDEX('%[^0-9]%',  
                    replace(name, '.','')
                ) -1
            )
        as int)

当它从数字开始时它总是有效的。它仅按第一个数字排序。如果您想先按数字排序,然后再按其余文本排序,您可以将最后一个查询更改为(我输入了相同的选择,以便显示有序的部分):

        select
        SUBSTRING(replace(name, '.',''),1,
                PATINDEX('%[^0-9]%',  
                    replace(name, '.','')
                ) -1
            ) as replacedDigit,
            SUBSTRING(replace(name, '.',''),
                PATINDEX('%[^0-9]%',  
                    replace(name, '.','')
                ), 100) as replacedText,

             name from #TMP order by 
        CAST( 
            SUBSTRING(replace(name, '.',''),1,
                PATINDEX('%[^0-9]%',  
                    replace(name, '.','')
                ) -1
            )
        as int), SUBSTRING(replace(name, '.',''),
                PATINDEX('%[^0-9]%',  
                    replace(name, '.','')
                ), 100)

【讨论】:

    【解决方案4】:

    试试这个

    SELECT  *
    FROM t
    ORDER BY 
            CASE PATINDEX('%[^0-9]%', PARSENAME(name, 4)) 
                WHEN 0 THEN RIGHT('0000' + PARSENAME(name, 4), 4) 
                WHEN 1 THEN PARSENAME(name, 1)
                ELSE RIGHT('0000' + SUBSTRING(PARSENAME(name, 2), 1, PATINDEX('%[^0-9]%', PARSENAME(name, 2)) - 1), 4) + SUBSTRING(PARSENAME(name, 2), PATINDEX('%[^0-9]%', PARSENAME(name, 2)), LEN(name))
            END
        ,   CASE PATINDEX('%[^0-9]%', PARSENAME(name, 3)) 
                WHEN 0 THEN RIGHT('0000' + PARSENAME(name, 3), 4) 
                WHEN 1 THEN PARSENAME(name, 1)
                ELSE RIGHT('0000' + SUBSTRING(PARSENAME(name, 2), 1, PATINDEX('%[^0-9]%', PARSENAME(name, 2)) - 1), 4) + SUBSTRING(PARSENAME(name, 2), PATINDEX('%[^0-9]%', PARSENAME(name, 2)), LEN(name))
            END
        ,   CASE PATINDEX('%[^0-9]%', PARSENAME(name, 2)) 
                WHEN 0 THEN RIGHT('0000' + PARSENAME(name, 2), 4) 
                WHEN 1 THEN PARSENAME(name, 1)
                ELSE RIGHT('0000' + SUBSTRING(PARSENAME(name, 2), 1, PATINDEX('%[^0-9]%', PARSENAME(name, 2)) - 1), 4) + SUBSTRING(PARSENAME(name, 2), PATINDEX('%[^0-9]%', PARSENAME(name, 2)), LEN(name))
            END
        ,   CASE PATINDEX('%[^0-9]%', PARSENAME(name, 1)) 
                WHEN 0 THEN RIGHT('0000' + PARSENAME(name, 1), 4) 
                WHEN 1 THEN PARSENAME(name, 1)
                ELSE RIGHT('0000' + SUBSTRING(PARSENAME(name, 2), 1, PATINDEX('%[^0-9]%', PARSENAME(name, 2)) - 1), 4) + SUBSTRING(PARSENAME(name, 2), PATINDEX('%[^0-9]%', PARSENAME(name, 2)), LEN(name))
            END
    

    为此:

    1.1.1.Question
    1.1.1.QuestionText
    1.1.1(a).Questions
    1.1.2.Questionswithtext
    1.1.2(b).Text
    2.1.1.Questions
    2.2.2.QuestionText
    10.1.1.Answers
    

    【讨论】:

      猜你喜欢
      • 2010-09-12
      • 2018-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      • 2010-12-11
      • 1970-01-01
      相关资源
      最近更新 更多