我VARCHAR在SQL 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(非数值的巨大值,最后排序),然后最后一部分处理字母.
请注意,对于大量数据,此查询的性能可能至少是可怕的.
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)
我认为两者都相当便携.
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)
这将按照您在问题中给出的顺序返回值.
所有进行转换的性能都不会太高,所以另一种方法是在表中添加另一列,在该表中存储数据的整数副本,然后先按照该列进行排序,然后再对相关列进行排序.这显然需要对插入或更新表中数据的逻辑进行一些更改,以填充两列.要么是这样,要么在表上插入触发器以在插入或更新数据时填充第二列.
您始终可以将 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 只会被修剪