使用字母数字条目对VARCHAR列进行排序(以数字开头)

时间:2017-07-27 16:14:28

标签: sql sql-server sql-server-2008

1
1one
2
2two
11
11eleven
11
22twentytwo
111oneeleven
552
3311
A1
A10
A11
A100
AB1
AB10
AB10A
AB100
AB100
B1
B2
B3
B3
B20
B20BB
B21BC
B21
B32

我想在下面的排序顺序中列出上面的列表。

1
2
11
11
552
3311
1one
2two
11eleven
22twentytwo
111oneeleven
A1
A10
A11
A100
AB1
AB10
AB10A
AB100
AB100
B1
B2
B3
B3
B20
B20BB
B21BC
B21
B32

查询是:

SELECT 
    Section,
    LEFT(Section, PATINDEX('%[0-9]%', Section) - 1) AS left1,
    PATINDEX('%[0-9]%', Section) startindex,
    LEN(Section) AS length,
    PATINDEX('%[0-9]%', REVERSE(Section)) AS revindex,
    LEN(Section) - PATINDEX('%[0-9]%', REVERSE(Section)) + 1 positionofendint,
    SUBSTRING(Section, PATINDEX('%[0-9]%', Section), LEN(Section) - PATINDEX('%[0-9]%', REVERSE(Section)) + 1) integerpart,
    LEN(Section) - PATINDEX('%[0-9]%', REVERSE(Section)) + 1 - PATINDEX('%[0-9]%', Section) + 1 subintlength,
    ISNUMERIC(section) isnumeric1,
    LEFT(Section, PATINDEX('[0-9]', Section)) onlyint
FROM 
    dbo.Section
WHERE 
    section NOT IN ('33A100', '55B32', '55B1', '55AB100', '99AB10A', '99B21BC', '1B20BB', '6B2B', '3AB1', '4a1', '7A11', '99B3')
    --where  section not like '%B%' and section not like '%A%' and section not like '%o%' and section not like '%e%' 
--ORDER BY section
--, CONVERT(INT,(case when isnumeric(section)=1 then section end))
ORDER BY  
    LEFT(Section, PATINDEX('%[0-9]%', Section) - 1), -- alphabetical sort
    CONVERT(INT, SUBSTRING(Section, PATINDEX('%[0-9]%', Section),
    LEN(Section) - PATINDEX('%[0-9]%', REVERSE(Section)) + 1 - PATINDEX('%[0-9]%', Section) + 1)) -- numerical sort

在这里,以字母开头的Word正在排序,旁边的数字也在排序,但是以数字开头的单词没有排序,请帮我解释如何用字符对单词的起始数字进行排序。

3 个答案:

答案 0 :(得分:1)

也许是一个简单的案例陈述?这并不特别匹配您的结果,但它正确地对varchar部分进行排序,在(可能是)和整数部分之后。

declare @table table (v varchar(64))
insert into @table
values
('1'),
('1one'),
('2'),
('2two'),
('11'),
('11eleven'),
('11'),
('22twentytwo'),
('111oneeleven'),
('552'),
('3311'),
('A1'),
('A10'),
('A11'),
('A100'),
('AB1'),
('AB10'),
('AB10A'),
('AB100'),
('AB100'),
('B1'),
('B2'),
('B3'),
('B3'),
('B20'),
('B20BB'),
('B21BC'),
('B21'),
('B32')

select v
from @table
order by case when v like '%[^0-9]%' then v end, v

答案 1 :(得分:1)

我相信你所追求的CASE是这样的:

SELECT Section
FROM dbo.Section
ORDER BY
    --Primary sort puts results that start with a letter to the end
    --Otherwise, sorts by where the occurrence of the first letter is
    CASE PATINDEX('%[^0-9]%', Section) WHEN 1 then 99 ELSE PATINDEX('%[^0-9]%', Section) END, 

    --Secondary sort will sort numeric values by length instead of number
    CASE PATINDEX('%[^0-9]%', Section) WHEN 1 then 99 ELSE LEN(Section) END, 

    --Final sort alpha-numeric
    Section

(感谢scsimon,他answer编写了测试此表所需的表创建。)

编辑:上面的查询会让您关闭,但字母数字排序有问题。它会在AB100(等)之前返回AB10A,会更深入地查看。

答案 2 :(得分:0)

尝试这样......

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

SELECT 
    x.SomeValue
    INTO #TestData
FROM
    ( VALUES 
        ('1'), ('1one'), ('2'), ('2two'), ('11'), ('11eleven'), ('11'), ('22twentytwo'), ('111oneeleven'),
        ('552'), ('3311'), ('A1'), ('A10'), ('A11'), ('A100'), ('AB1'), ('AB10'), ('AB10A'), ('AB100'),
        ('AB100'), ('B1'), ('B2'), ('B3'), ('B3'), ('B20'), ('B20BB'), ('B21BC'), ('B21'), ('B32')
    ) x (SomeValue);

SELECT 
    td.SomeValue
FROM
    #TestData td

ORDER BY 

    CASE WHEN td.SomeValue NOT LIKE '%[^0-9]%' THEN CAST(td.SomeValue AS INT) ELSE 2147483647 END,
    CASE WHEN LEFT(td.SomeValue, 1) BETWEEN '0' AND '9' AND td.SomeValue LIKE '%[^0-9]%' THEN CAST(SUBSTRING(td.SomeValue, 1, PATINDEX('%[^0-9]%', td.SomeValue) - 1) AS INT) ELSE 2147483647 END,      
    td.SomeValue;
HTH,Jason

相关问题