有没有办法按字母数字列排序?

Ris*_*osh 5 t-sql sql-server-2012

我有一个表单位

单位名称
单元1
2b单元
2c单元
单元2a
单元10
单元3a
3c单元
第11单元

我想排序相同

单位名称
单元1
单元2a
2b单元
2c单元
单元3a
3c单元
单元10
第11单元

我们如何在 t-sql 中实现这一点?

数据定义语言

create table units (unitname varchar(20))
insert into units values ('unit 1'),('unit 2b'),('unit 2c'),
('unit 2a'),('unit 10'),('unit 3a'),('unit 3c'),('unit 11')
Run Code Online (Sandbox Code Playgroud)

Pau*_*ite 5

对于给定的示例值:

SELECT 
    U.unitname
FROM dbo.units AS U
ORDER BY
    COALESCE
    (
        TRY_CONVERT(integer, SUBSTRING(U.unitname, 6, 2)),
        TRY_CONVERT(integer, SUBSTRING(U.unitname, 6, 1))
    ),
    RIGHT(U.unitname, 1);
Run Code Online (Sandbox Code Playgroud)

这个想法是按照可以成功转换为整数的最大字符数进行排序,打破与最终字符的联系。

或者,这个想法插入足够的前缀零,使字符排序按预期工作:

SELECT 
    U.unitname
FROM dbo.units AS U
ORDER BY
    STUFF
    (
        U.unitname, 
        PATINDEX('%[0123456789]%', U.unitname),
        0, 
        REPLICATE
        (
            '0', 
            -- varchar(20) less the length of the existing text
            20 - DATALENGTH(U.unitname) +
            -- Plus extra zeros for trailing non-numeric characters
            PATINDEX('%[0123456789]%', REVERSE(U.unitname))
        )
    );
Run Code Online (Sandbox Code Playgroud)

两者都返回:

单位名称
单元1
单元2a
2b单元
2c单元
单元3a
3c单元
单元10
第11单元

db<>fiddle在线演示


更好的表格设计可能是:

CREATE TABLE dbo.Unit
(
    UnitNo tinyint NOT NULL
        CONSTRAINT [CK dbo.Unit UnitNo positive]
            CHECK (UnitNo > 0),
    UnitSuffix char(1) COLLATE Latin1_General_BIN2 NOT NULL
        CONSTRAINT [CK dbo.Unit Suffix blank or a-z]
            CHECK (UnitSuffix LIKE '[ a-z]'),

    CONSTRAINT [PK dbo.Unit UnitNo, UnitSuffix]
        PRIMARY KEY CLUSTERED (UnitNo, UnitSuffix)
);

INSERT dbo.Unit
    (UnitNo, UnitSuffix)
VALUES
    (1, ''),
    (2, 'b'),
    (2, 'c'),
    (2, 'a'),
    (3, 'a'),
    (3, 'c'),
    (10, ''),
    (11, '');

SELECT
    unitname = CONCAT('unit ', U.UnitNo, U.UnitSuffix)
FROM dbo.Unit AS U 
ORDER BY 
    U.UnitNo, 
    U.UnitSuffix;
Run Code Online (Sandbox Code Playgroud)