我在VARCHAR
数据库中有一个SQL Server 2000
列,可以包含字母或数字。这取决于客户在前端配置应用程序的方式。
当它确实包含数字时,我希望它以数字方式排序,例如为“1”,“2”,“10”而不是“1”,“10”,“2”。只包含字母,字母和数字(如'A1')的字段可以按字母顺序排序。例如,这将是一个可接受的排序顺序。
1
2
10
A
B
B1
实现这一目标的最佳方法是什么?
答案 0 :(得分:70)
一种可能的解决方案是使用前面的字符填充数值,使所有字符串长度相同。
以下是使用该方法的示例:
select MyColumn
from MyTable
order by
case IsNumeric(MyColumn)
when 1 then Replicate('0', 100 - Len(MyColumn)) + MyColumn
else MyColumn
end
100
应替换为该列的实际长度。
答案 1 :(得分:12)
有几种方法可以做到这一点。
一个是
SELECT
...
ORDER BY
CASE
WHEN ISNUMERIC(value) = 1 THEN CONVERT(INT, value)
ELSE 9999999 -- or something huge
END,
value
ORDER BY的第一部分将所有内容转换为int(非数值的巨大值,最后排序),然后最后一部分处理字母表。
请注意,对于大量数据,此查询的性能可能至少是可怕的。
答案 2 :(得分: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
这将按照您在问题中提供的顺序返回值。
对于所有正在进行的转换,性能不会太高,所以另一种方法是在表中添加另一列,在该表中存储数据的整数副本,然后先按照该列进行排序,然后再对相关列进行排序。这显然需要对插入或更新表中数据的逻辑进行一些更改,以填充两列。要么是这样,要么在表格上设置一个触发器,以便在插入或更新数据时填充第二列。
答案 3 :(得分:5)
SELECT *, CONVERT(int, your_column) AS your_column_int
FROM your_table
ORDER BY your_column_int
OR
SELECT *, CAST(your_column AS int) AS your_column_int
FROM your_table
ORDER BY your_column_int
我认为两者都相当便携。
答案 4 :(得分:4)
我在“订单”部分
中以非常简单的方式解决了这个问题ORDER BY (
sr.codice +0
)
ASC
这看起来效果很好,事实上我进行了以下排序:
16079 Customer X
016082 Customer Y
16413 Customer Z
因此0
前面的16082
被认为是正确的。
答案 5 :(得分:4)
总是可以将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
第一个排序列将数字放在顶部。 第二种按长度排序,所以10将在0001之前(这是愚蠢的?!)
这导致了第二个版本:
SELECT
*
FROM
Table
ORDER BY
ISNUMERIC([yourvarchar] +'e0') DESC
, RIGHT('00000000000000000000'+[yourvarchar], 20) ASC
第二列现在正确填充'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
现在数字首先用'0'字符填充(当然,长度20可以增强) - 对数字进行排序 - 而alpha只会被修剪
答案 6 :(得分:2)
这似乎有效:
select your_column
from your_table
order by
case when isnumeric(your_column) = 1 then your_column else 999999999 end,
your_column
答案 7 :(得分:1)
此查询对您有所帮助。在此查询中,列具有数据类型varchar按良好顺序排列。例如 - 在此列中数据为: - 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;
答案 8 :(得分:0)
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
根据this link你需要转换为MONEY然后INT以避免将'$'作为数字排序。
答案 9 :(得分:0)
这可能会对你有所帮助,当我遇到同样的问题时,我已经尝试过这个。
SELECT *
FROM tab
ORDER BY IIF(TRY_CAST(val AS INT) IS NULL, 1, 0),TRY_CAST(val AS INT);
答案 10 :(得分:-1)
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