2016-09-12 114 views
5

任何人都可以帮助我如何排序?
我有一个模式的动态列表,我想排序,它包含字母数字值和字母。Sql Server 2008中的字母数字排序

CREATE TABLE dbo.Pattern (Pattern varchar(50) NULL) 
INSERT INTO dbo.Pattern (Pattern) VALUES ('A11') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('A12') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('A8') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('A2') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('B6') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('B21') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('B10') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('B3') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('B100') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('B2') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('AA') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('BA') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('A20') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('AB') 
INSERT INTO dbo.Pattern (Pattern) VALUES ('BB') 

SELECT Pattern FROM dbo.Pattern ORDER BY Pattern 

DROP Table dbo.Pattern 

结果表明这样的:

A11 
A12 
A2 
A20 
A8 
AA 
AB 
B10 
B100 
B2 
B21 
B3 
B6 
BA 
BB 

但我要表明的是这样的结果:

AA 
A1 
A2 
A8 
A11 
A12 
A20 
AB 
BA 
B2 
B3 
B6 
B10 
B21 
B100 
BB 
+2

加1样本数据 – TheGameiswar

+0

您可以定义所需结果背后的逻辑吗?为什么'AA'会出现在'B100'之后? “AAA”和“BA1”之间会先出现哪一个?为什么?如果你可以定义逻辑,我敢打赌,你很容易回答你自己的问题。 –

+0

@TabAlleman,我已经编辑了应该为模式排序输出的结果的内容。 – itsMacyAnn

回答

1
SELECT Pattern 
FROM dbo.Pattern 
ORDER BY LEFT(Pattern,1), 
     CASE WHEN SUBSTRING(Pattern,2,LEN(Pattern)) LIKE '%[0-9]%' THEN CAST(SUBSTRING(Pattern,2,LEN(Pattern)) as int) 
      WHEN SUBSTRING(Pattern,2,LEN(Pattern)) = 'A' THEN 0 
      ELSE 10000000 END, 
      SUBSTRING(Pattern,2,LEN(Pattern)) 

将输出:

Pattern 
AA 
A2 
A8 
A11 
A12 
A20 
AB 
BA 
B2 
B3 
B6 
B10 
B21 
B100 
BB 
1

为了您的样本数据,此接近:

order by left(pattern, patindex('%[0-9]%', pattern)), 
     patindex('%[0-9]%', pattern), 
     len(pattern) asc, 
     pattern 

但是,你想全部阿尔法是最后一次,所以case需要(我认为):

order by left(pattern, patindex('%[0-9]%', pattern)), 
     (case when pattern like '%[0-9]%' 
       then patindex('%[0-9]%', pattern) 
       else 999 
      end), 
     len(pattern) asc, 
     pattern 
+0

它没有像上面提到的那样返回输出。为什么? – Susang

+0

那么这个逻辑意味着'B1'会在'A10'之前出现,因为它的长度更短。 –

+0

@Suraz。 。 。你已经有了答案,但我仍然修正了这个问题。 –

1
SELECT Pattern 
FROM dbo.Pattern 
ORDER BY CASE WHEN PATINDEX('%[0-9]%', Pattern) > 0 
       THEN LEFT(Pattern, PATINDEX('%[0-9]%', Pattern)-1) 
       ELSE Pattern 
     END, 
     CASE WHEN PATINDEX('%[0-9]%', Pattern) > 0 
       THEN CONVERT(INT, SUBSTRING(Pattern, PATINDEX('%[0-9]%', Pattern), LEN(Pattern))) 
       ELSE 0 
     END 

请在发布前搜索网和堆栈溢出。

参考:http://www.essentialsql.com/use-sql-server-to-sort-alphanumeric-values/

+0

它返回'传递给LEFT或SUBSTRING函数的无效长度参数.'错误。抛出'AA','BA'的错误,因为它们没有数字值,所以'LEFT('AA',0 - 1)'抛出错误。 – Arulkumar

+0

消息537,级别16,状态2,行1 传递给LEFT或SUBSTRING函数的长度参数无效。 – itsMacyAnn

+0

@ayakamacy我更新了我的答案,使用'CASE'表达式来处理只包含字母的图案。 –

0

我会分体字母和num部分:

ORDER BY 
    CASE WHEN PATINDEX('%[0-9]%', Pattern)=0 THEN 1 ELSE 0 END,--Put no-nums last 
    CASE WHEN PATINDEX('%[0-9]%', Pattern) != 0 THEN LEFT(Pattern, PATINDEX('%[0-9]%', Pattern)-1) ELSE Pattern END, 
    CASE WHEN PATINDEX('%[0-9]%', Pattern) != 0 THEN SUBSTRING(Pattern, PATINDEX('%[0-9]%', Pattern), LEN(Pattern)) END 
0

使用交叉适用于简化行计算

select pattern 
from pattern 
cross apply (
    select leftLen = isnull(nullif(patindex('%[0-9]%', pattern),0) - 1, len(pattern)) 
      ,totalLen = len(pattern) 
    ) c 
order by 
case leftLen when totalLen then 2 else 1 end, 
left(Pattern, leftLen), 
cast(right(Pattern, totalLen-leftLen) as int)