T-SQL查询按字母顺序对列进行排序,但结束编号除外

时间:2017-05-16 14:54:33

标签: sql-server

如何编写T-SQL查询以按字母顺序对列进行排序,并将结束编号作为数值?

换句话说,我不会考虑可能位于字符串中间的数字,以简化问题。

以示例:

a1XBNR1
a1XBNR10  <-- this should go after a1BRN2
a1XBNR2

这是一个无法正确排序的示例代码:

-- Alphanumeric sorting with T-SQL

USE [AdventureWorks2012]
GO

CREATE TABLE dbo.TestTable
(
       id varchar(50) NULL
)

DELETE dbo.TestTable
GO

INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XANR1')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XANR10')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XANR2')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XANR20')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XANR3')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XB11')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('a1XB2')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('b1XBNR20')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('b1XB30')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('b1XB2')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('AB100')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('1')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('AB1')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('A1')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('B2')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('A11')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('B20')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('B21')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('AB10')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('B3')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('AB100')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('2')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('B1')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('B32')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('11')
INSERT INTO dbo.TestTable (TestTable.id) VALUES ('A10')


-- Attempt 1 - Syntax not supported by T-SQL
SELECT *
FROM   db.TestTable
ORDER  BY left(id, 1)  -- 1st letter as text
     , substring(fest, '\d+')::int NULLS FIRST  -- first number in string as int
     , id  -- whole columns as cheap tiebreaker

-- Attempt 2 - cannot have digit in the middle of the string
-- Error: Conversion failed when converting the varchar value '1XBNR1' to data type int.
SELECT id
FROM dbo.TestTable
ORDER BY LEFT(id,PATINDEX('%[0-9]%',id)-1), -- alphabetical sort
         CONVERT(INT,SUBSTRING(id,PATINDEX('%[0-9]%',id),LEN(id))) -- numerical 

1 个答案:

答案 0 :(得分:3)

在尾随数字前面的左边部分使用patindex()reverse()顺序,并将最后一组数字转换为其余部分的整数。

select *
from testtable t
order by 
    left(id,len(id)-patindex('%[^0-9]%',reverse(id))+1)
  , convert(int,right(id,patindex('%[^0-9]%',reverse(id)+' ')-1))

rextester演示:blog post at this link

返回:

+----------+
|    id    |
+----------+
| 1        |
| 11       |
| 2        |
| A1       |
| A10      |
| A11      |
| a1XANR1  |
| a1XANR2  |
| a1XANR3  |
| a1XANR10 |
| a1XANR20 |
| a1XB2    |
| a1XB11   |
| AB1      |
| AB10     |
| AB100    |
| AB100    |
| B1       |
| B2       |
| B3       |
| B20      |
| B21      |
| B32      |
| b1XB2    |
| b1XB30   |
| b1XBNR20 |
+----------+
相关问题