2017-07-27 25 views
-2
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 

我想按照以下排列顺序在上面的列表中。使用字母数字条目排序VARCHAR列(以数字开头)

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 

这里,话语开始与字母表排序和旁边号码也是排序,但字开始的数字进行排序,请帮助我如何排序这个词开始与字符的数字。

+0

你不能拥有MySQL和SQL-SERVER,请删除您不使用 – Eli

+2

顺序的关系数据库管理系统的标签你说明你想要的是非常困难的,因为你在排序中混合了数据类型。您只想首先对所有数字值进行排序,并且需要按照数字排序,而不是字符数据,然后您希望包含字符数据的值以相同的方式排序。你真的不能这样做。 –

+0

@SeanLange我相信我已经想出了一个解决方案,但你非常欢迎告诉我,我犯了什么可怕的错误:) **编辑:**自己实现了。我很接近,但是我的字母数字排序会混淆像'AB10A'之前的* AB100'之类的值。 – Santi

回答

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 
+0

这很不错,但实际上OP希望以非常困难的方式对这些数据进行排序。注意字符数据是如何按数字和字符排序的? –

+0

我同意@SeanLange,它几乎看起来像你必须先排序的第一个怎么样呢?奇怪我同意,但它会让他们开始。 – scsimon

+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(等),将会更深入地看。

+1

这很接近,但还不够。第二轮排序需要根据字符数据的前导号进行排序。要看到这项工作不正确地将'2two'改为'2to'。这种分类非常糟糕。 –

+0

是的,我刚刚意识到,谢谢。有时候暂时把自己烧掉了,但计划稍后再回到制图板。 – Santi

+0

感谢您的回复,它几乎接近,只有AB100先来 – sreehari

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,杰森