SQL字母数字排序问题

标签 sql sql-server sql-server-2008 natural-sort

我发现我们可以对表中的列进行排序,即使它是字母数字。

这里我遇到的唯一问题是,如果列数据只是字符,它会抛出错误。

BEGIN TRAN

USE SomeDatabase
CREATE TABLE dbo.Section
(
       Section varchar(50) NULL
)
INSERT INTO dbo.Section (Section.Section) VALUES ('BB')
INSERT INTO dbo.Section (Section.Section) VALUES ('1 ')
INSERT INTO dbo.Section (Section.Section) VALUES ('AB 1')
INSERT INTO dbo.Section (Section.Section) VALUES ('A21')
INSERT INTO dbo.Section (Section.Section) VALUES ('B2')
INSERT INTO dbo.Section (Section.Section) VALUES ('A11')
INSERT INTO dbo.Section (Section.Section) VALUES ('B20')
INSERT INTO dbo.Section (Section.Section) VALUES ('B21')
INSERT INTO dbo.Section (Section.Section) VALUES ('AB10')
INSERT INTO dbo.Section (Section.Section) VALUES ('A10')
SELECT Section
FROM dbo.Section

SELECT Section
FROM dbo.Section
ORDER BY LEFT(Section,PATINDEX('%[0-9]%',Section)-1), -- alphabetical sort
         CONVERT(INT,SUBSTRING(Section,PATINDEX('%[0-9]%',Section),LEN(Section))) -- numerical sort

DROP Table dbo.Section

ROLLBACK

因此,对“BB”进行排序就是问题所在。如果您删除 BB,那么一切正常。

最佳答案

从您的代码来看,明显的问题是 PATINDEX 如果未找到任何内容,将返回 0。因为您随后将 0 - 1 作为长度,所以 LEFT 函数将抛出错误。

试试这个:

...
ORDER BY LEFT(Section
             ,CASE WHEN PATINDEX('%[0-9]%',Section) >= 2
                   THEN PATINDEX('%[0-9]%',Section) - 1
                   ELSE LEN(Section)
                   END
             ), -- alphabetical sort
     CASE WHEN PATINDEX('%[0-9]%',Section) >= 1
          THEN CONVERT(INT,SUBSTRING(Section,PATINDEX('%[0-9]%',Section),LEN(Section) - PATINDEX('%[0-9]%',Section) - 1))
          END -- numerical sort
...

关于SQL字母数字排序问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45845961/

相关文章:

mysql - 跨多对多关系表的唯一约束

sql - 如何使用一个 sql 查询为每个条件创建一个单独的列?

sql - 我该如何优化这个查询?

MS sql 服务器中的 mysql REGEXP

选择查询中的 SQL 条件变量

sql-server-2008 - 使用另一个存储过程中的参数调用存储过程的正确语法

sql-server-2008 - SSRS 报告格式化表格以并排显示数据

sql-server-2008 - SQL Server 2008 列仅存在于一张表中

mysql - str_to_date 不起作用

c# - 自动生成不是 Entity Framework 中主键的 GUID 列