如何在包含数字的SQL Server中对VARCHAR列进行排序?

Tim*_*m C 50 sql t-sql

VARCHARSQL Server 2000数据库中有一个列,可以包含字母或数字.这取决于客户在前端配置应用程序的方式.

当它确实包含数字时,我希望它以数字方式排序,例如"1","2","10"而不是"1","10","2".只包含字母,字母和数字(如'A1')的字段可以按字母顺序排序.例如,这将是可接受的排序顺序.

1
2
10
A
B
B1
Run Code Online (Sandbox Code Playgroud)

实现这一目标的最佳方法是什么?

Ale*_*ris 75

一种可能的解决方案是使用前面的字符填充数值,以便所有字符串具有相同的字符串长度.

以下是使用该方法的示例:

select MyColumn
from MyTable
order by 
    case IsNumeric(MyColumn) 
        when 1 then Replicate('0', 100 - Len(MyColumn)) + MyColumn
        else MyColumn
    end
Run Code Online (Sandbox Code Playgroud)

100应与该列的实际长度来代替.


Cow*_*wan 12

有几种可能的方法可以做到这一点.

一个是

SELECT
 ...
ORDER BY
  CASE 
    WHEN ISNUMERIC(value) = 1 THEN CONVERT(INT, value) 
    ELSE 9999999 -- or something huge
  END,
  value
Run Code Online (Sandbox Code Playgroud)

ORDER BY的第一部分将所有内容转换为int(非数值的巨大值,最后排序),然后最后一部分处理字母.

请注意,对于大量数据,此查询的性能可能至少是可怕的.


Joh*_*hnB 6

SELECT *, CONVERT(int, your_column) AS your_column_int
FROM your_table
ORDER BY your_column_int
Run Code Online (Sandbox Code Playgroud)

要么

SELECT *, CAST(your_column AS int) AS your_column_int
FROM your_table
ORDER BY your_column_int
Run Code Online (Sandbox Code Playgroud)

我认为两者都相当便携.

  • 正如OP所说,'your_column`也包括字母.您提出的解决方案不适用于包括字母在内的值. (3认同)

Luk*_*ett 5

select
  Field1, Field2...
from
  Table1
order by
  isnumeric(Field1) desc,
  case when isnumeric(Field1) = 1 then cast(Field1 as int) else null end,
  Field1
Run Code Online (Sandbox Code Playgroud)

这将按照您在问题中给出的顺序返回值.

所有进行转换的性能都不会太高,所以另一种方法是在表中添加另一列,在该表中存储数据的整数副本,然后先按照该列进行排序,然后再对相关列进行排序.这显然需要对插入或更新表中数据的逻辑进行一些更改,以填充两列.要么是这样,要么在表上插入触发器以在插入或更新数据时填充第二列.


Ber*_*ard 5

您始终可以将 varchar-column 转换为 bigint,因为整数可能太短...

select cast([yourvarchar] as BIGINT)
Run Code Online (Sandbox Code Playgroud)

但你应该总是关心字母字符

where ISNUMERIC([yourvarchar] +'e0') = 1
Run Code Online (Sandbox Code Playgroud)

+'e0' 来自http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/isnumeric-isint-isnumber

这会导致你的陈述

SELECT
  *
FROM
  Table
ORDER BY
   ISNUMERIC([yourvarchar] +'e0') DESC
 , LEN([yourvarchar]) ASC
Run Code Online (Sandbox Code Playgroud)

第一个排序列将把数字放在最上面。第二个按长度排序,所以 10 将在 0001 之前(这是愚蠢的?!)

这导致了第二个版本:

SELECT
      *
    FROM
      Table
    ORDER BY
       ISNUMERIC([yourvarchar] +'e0') DESC
     , RIGHT('00000000000000000000'+[yourvarchar], 20) ASC
Run Code Online (Sandbox Code Playgroud)

第二列现在用“0”正确填充,因此自然排序将带前导零的整数(0,01,10,0100...)按正确顺序(正确!) - 但所有 alpha 都将用“0”增强-chars(性能)

所以第三个版本:

 SELECT
          *
        FROM
          Table
        ORDER BY
           ISNUMERIC([yourvarchar] +'e0') DESC
         , CASE WHEN ISNUMERIC([yourvarchar] +'e0') = 1
                THEN RIGHT('00000000000000000000' + [yourvarchar], 20) ASC
                ELSE LTRIM(RTRIM([yourvarchar]))
           END ASC
Run Code Online (Sandbox Code Playgroud)

现在数字首先用 '0'-chars 填充(当然,长度 20 可以增强) - 对数字进行正确排序 - 并且 alphas 只会被修剪