如何sortingSQL Server中包含数字的VARCHAR列?

我有一个SQL Server 2000数据库中的VARCHAR列,可以包含字母或数字。 这取决于如何在客户的前端configuration应用程序。

当它包含数字时,我希望它被数字sorting,例如,如“1”,“2”,“10”而不是“1”,“10”,“2”。 包含字母,字母和数字(如“A1”)的字段可按照字母顺序排列。 例如,这将是一个可接受的sorting顺序。

 1 2 10 A B B1 

达到这个目标的最好方法是什么?

一种可能的解决scheme是用前面的字符填充数字值,以便所有string具有相同的string长度。

这是一个使用这种方法的例子:

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

100应该replace为该列的实际长度。

有几种可能的方法来做到这一点。

一个会的

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

ORDER BY的第一部分将所有内容都转换为int(对于非数字来说是一个巨大的值,最后sorting),那么最后一部分将处理字母顺序。

请注意,此查询的性能可能至less在大量数据上适度可怕。

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

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

性能不会太高,所有的投射,所以另一种方法是添加另一列到您存储数据的整数副本的表,然后按照那个问题先sorting。 这显然需要对表中插入或更新数据的逻辑进行一些更改,以填充两个列。 要么是这样,要么在表中放置一个触发器,以在插入或更新数据时填充第二列。

 SELECT *, CONVERT(int, your_column) AS your_column_int FROM your_table ORDER BY your_column_int 

要么

 SELECT *, CAST(your_column AS int) AS your_column_int FROM your_table ORDER BY your_column_int 

我认为两者都相当便携。

我用一个非常简单的方法把它写在“订单”部分

 ORDER BY ( sr.codice +0 ) ASC 

这似乎工作得很好,其实我有以下sorting:

 16079 Customer X 016082 Customer Y 16413 Customer Z 

所以16082前面的0被认为是正确的。

你总是可以将你的varchar-column转换为bigint,因为整数可能太短…

 select cast([yourvarchar] as BIGINT) 

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

 where ISNUMERIC([yourvarchar] +'e0') = 1 

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

这会导致你的陈述

 SELECT * FROM Table ORDER BY ISNUMERIC([yourvarchar] +'e0') DESC , LEN([yourvarchar]) ASC 

第一个sorting列将数字放在顶部。 第二种按长度sorting,所以10会在0001之前(这是愚蠢的?!)

这导致了第二个版本:

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

第二列现在正确填充'0',所以自然sorting将前导零(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 

现在数字首先填充'0'字符(当然,长度20可以增强) – 哪种数字是正确的 – 阿尔法只能得到修剪

这似乎工作:

 select your_column from your_table order by case when isnumeric(your_column) = 1 then your_column else 999999999 end, your_column 
 SELECT FIELD FROM TABLE ORDER BY isnumeric(FIELD) desc, CASE ISNUMERIC(test) WHEN 1 THEN CAST(CAST(test AS MONEY) AS INT) ELSE NULL END, FIELD 

根据这个链接,你需要投钱MONEY然后INT,以避免订购'$'作为一个数字。

这个查询对你有帮助。 在这个查询中,一个列的数据typesvarchar是按顺序排列的。例如 – 在这一列中的数据是:–G1,G34,G10,G3。 所以,运行这个查询后,你会看到结果: – G1,G10,G3,G34。

 SELECT *, (CASE WHEN ISNUMERIC(column_name) = 1 THEN 0 ELSE 1 END) IsNum FROM table_name ORDER BY IsNum, LEN(column_name), column_name; 
  SELECT *, ROW_NUMBER()OVER(ORDER BY CASE WHEN ISNUMERIC (ID)=1 THEN CONVERT(NUMERIC(20,2),SUBSTRING(Id, PATINDEX('%[0-9]%', Id), LEN(Id)))END DESC)Rn ---- numerical FROM ( SELECT '1'Id UNION ALL SELECT '25.20' Id UNION ALL SELECT 'A115' Id UNION ALL SELECT '2541' Id UNION ALL SELECT '571.50' Id UNION ALL SELECT '67' Id UNION ALL SELECT 'B48' Id UNION ALL SELECT '500' Id UNION ALL SELECT '147.54' Id UNION ALL SELECT 'A-100' Id )A ORDER BY CASE WHEN ISNUMERIC (ID)=0 /* alphabetical sort */ THEN CASE WHEN PATINDEX('%[0-9]%', Id)=0 THEN LEFT(Id,PATINDEX('%[0-9]%',Id)) ELSE LEFT(Id,PATINDEX('%[0-9]%',Id)-1) END END DESC