MS SQL 排序字母数字值(1、2、3、5、6、7、9、10、4a、8a、4b、8b)[重复]

MS SQL Sort Alphanumeric values (1, 2, 3, 5, 6, 7, 9, 10, 4a, 8a, 4b, 8b) [duplicate]

提问人:Fadl Assaad 提问时间:4/16/2023 更新时间:4/16/2023 访问量:43

问:

在 SQL 数据库 (2005/2008) 中,我有一个名为 Ordernumber 的字段,具有以下值:1、2、3、5、6、7、9、10、4a、8a、4b、8b 我想要一种方法将它们排序为 1、2、3、4a、4b、5、6、7、8a、8b、9、10。怎么办?

我使用了以下内容:

SELECT Ordernumber
FROM alphanumericorder
ORDER BY
  CASE
    WHEN ISNUMERIC(Ordernumber) = 1 THEN CAST(Ordernumber AS INT)
    ELSE CAST(SUBSTRING(Ordernumber, 1, PATINDEX('%[0-9]%', Ordernumber) - 1) AS VARCHAR(100)) 
      + RIGHT('0000000000' + CAST(SUBSTRING(Ordernumber, PATINDEX('%[0-9]%', Ordernumber), LEN(Ordernumber)) AS VARCHAR(100)), 10)
  END

但我收到以下错误:“将 varchar 值”0000000004a“转换为数据类型 int 时转换失败”

然后我用了:

  SELECT Ordernumber
FROM alphanumericorder
ORDER BY
  CASE
    WHEN ISNUMERIC(LEFT(Ordernumber,1)) = 1 THEN CAST(Ordernumber AS INT)
    ELSE CAST(LEFT(Ordernumber,LEN(Ordernumber)-1) AS VARCHAR(100)) 
      + RIGHT('0000000000' + CAST(RIGHT(Ordernumber,1) AS VARCHAR(100)), 1)
  END;

我得到:“将 nvarchar 值”4a“转换为数据类型 int 时转换失败”

请指教。

服务器 2008 SQL Server 2005

评论

0赞 Thom A 4/16/2023
2005 年和 2008 年都在大约 3/8 年的时间里无支撑地完成;您确实需要实施升级计划。你真的在用哪个?两者都缺乏许多在更“现代”版本中理所当然的基本功能。
0赞 Fadl Assaad 4/16/2023
您好@ThomA,实际上这是一个生产数据库,并且有很多基于旧版本 SQL 的依赖项,我们去年计划转换它,但这是一场噩梦,因为很多 SP 都有错误,所以我们要求 SQL 专业人员提供解决方法或任何自定义解决方案。
3赞 Tim Biegeleisen 4/16/2023
这里最好的办法是将主要版本和次要版本存储在单独的列中,即 store 和 和 。4a4a
0赞 siggemannen 4/16/2023
问题在于 CASE 的一部分是 INT,因此 ELSE 部分也必须转换为 INT。这不起作用,因为您有一个字符串值
0赞 Fadl Assaad 4/16/2023
@TimBiegeleisen,有没有办法在查询时做到这一点?我的意思是创建一个存储过程,将订单号拆分为许多字段,然后对它们进行排序?我在SQL方面没有太多经验,但我所知道的是,对于我们来说,创建多个列作为用户已经输入的1000 +记录为时已晚。

答:

0赞 siggemannen 4/16/2023 #1

像这样的东西怎么样:

select *
from (
    VALUES  (N'1')
    ,   (N'2')
    ,   (N'3')
    ,   (N'5')
    ,   (N'6')
    ,   (N'7')
    ,   (N'9')
    ,   (N'10')
    ,   (N'4a')
    ,   (N'8a')
    ,   (N'4b')
    ,   (N'8b')
) t ([Ordernumber])
order by CASE
    WHEN ISNUMERIC(Ordernumber) = 1 THEN CAST(Ordernumber AS INT)
    ELSE CAST(SUBSTRING(Ordernumber, 1, PATINDEX('%[^0-9]%', Ordernumber)-1) AS INT)
  END, OrderNumber

这将通过从第一个非编号数字中删除所有内容来转换订单号的数字部分

评论

0赞 Fadl Assaad 4/16/2023
嗨,您的解决方案完成了大部分技巧,但是我在结果中得到了 8b 之前的 8b,而我得到了 4a,然后像预期的那样得到了 4b,很奇怪。
0赞 siggemannen 4/16/2023
好的捕获,我稍微更改了代码,并添加了一个决胜局作为 OrderNumber,这应该可以解决我认为的问题
0赞 Fadl Assaad 4/16/2023
谢谢,这成功了:)我将您的回复标记为答案。
0赞 Charlieface 4/16/2023
ISNUMERIC做一些奇怪的事情,应该避免,要好得多。TRY_CAST AS int