如何在C#中对nvarchar类型的公里/杆号拼接列升序排序?
解决NVARCHAR拼接字段的数值排序问题
哈哈,这个坑我踩过好多次!当你把数值相关的内容存在NVARCHAR字段里,直接排序会按字符顺序来,而不是我们想要的数值大小,这就导致了19/26排在2.3/14前面的尴尬情况——毕竟字符'1'比'2'小,但数值19可是比2.3大得多。
最优解决方案:直接用原始字段排序
既然你的FROM_KM是fromkm和frompole拼接出来的,那直接对这两个原始字段做类型转换后排序就好,比先拼接再拆分效率高多了:
SELECT fromkm + '/' + frompole AS FROM_KM FROM station ORDER BY CAST(fromkm AS DECIMAL(10,2)), -- 把公里数字符串转成小数,按数值排序 CAST(frompole AS INT) -- 公里数相同时,按杆号的整数大小排序
备选方案:基于拼接后的字段排序(不推荐)
如果因为某些限制,必须用已经拼接好的FROM_KM字段来排序,那可以用字符串函数拆分出斜杠前后的部分,再转成数值类型:
SELECT FROM_KM FROM ( SELECT fromkm + '/' + frompole AS FROM_KM FROM station ) t ORDER BY CAST(LEFT(FROM_KM, CHARINDEX('/', FROM_KM) - 1) AS DECIMAL(10,2)), CAST(RIGHT(FROM_KM, LEN(FROM_KM) - CHARINDEX('/', FROM_KM)) AS INT)
原理说明
CAST(fromkm AS DECIMAL(10,2))会把字符串形式的公里数(不管是整数1还是小数1.3)转换成数值类型,这样排序时就会遵循数值大小的逻辑,而不是字符的ASCII顺序。CAST(frompole AS INT)则把杆号的字符串转成整数,确保杆号也是按数值排序(比如0会排在44前面)。
用上面的SQL跑你的测试数据,就能得到你想要的结果:
1/0、1.3/44、2.3/14、19/26、22/21、29/0、85/30
长期优化建议
如果这个排序需求是经常用到的,建议把fromkm字段改成DECIMAL类型,frompole改成INT类型——这样不仅排序更高效,后续的查询、计算也能避免很多字符串转数值的麻烦。
内容的提问来源于stack exchange,提问作者M. Usaid
相关产品推荐
相关产品推荐

