2013-05-31 33 views
6

我使用SQL Server排序VARCHAR列,该列是一个VARCHAR(50),我想这样的排序是:字母数字输入

1A   
1B   
2   
2   
3   
4A   
4B   
4C   
5A   
5B   
5C   
5N   
14 Draft   
21   
22A   
22B   
23A   
23B   
23C   
23D   
23E   
25   
26   
FR01584   
MISC 

我至今是:

Select * 
From viewASD 
ORDER BY 
    Case When IsNumeric(LEFT(asdNumNew,1)) = 1 
     Then CASE When IsNumeric(asdNumNew) = 1 
        Then Right(Replicate('0',20) + asdNumNew + '0', 20) 
        Else Right(Replicate('0',20) + asdNumNew, 20) 
       END 
     When IsNumeric(LEFT(asdNumNew,1)) = 0 
     Then Left(asdNumNew + Replicate('',21), 20) 
    End 

但是这个SQL语句在'26'后面放了'14草案'。

有人可以帮忙吗?谢谢

回答

3

你的WHERE语句是......非常复杂。

它看起来像你想按整数顺序排序的任何前导数字,然后按余数排序。如果是这样,你应该把它作为单独的条款来做,而不是试图在一个中做到这一点。您遇到的具体问题是您只允许输入一位数字,而不是两位或更多。 (并且有No such thing as two。)

下面是您的修补程序以及SQLFiddle,对您的ORDER BY使用两个单独的计算列测试。 (注意,这个假设的asdNumNew数字部分将装配在一个T-SQL int;如果没有,则需要调整CAST和第一ELSE最大值)。

SELECT * FROM viewASD 
ORDER BY 
CASE 
    WHEN ISNUMERIC(asdNumNew)=1 
    THEN CAST(asdNumNew as int) 

    WHEN PATINDEX('%[^0-9]%',asdNumNew) > 1 
    THEN CAST(
    LEFT(
     asdNumNew, 
     PATINDEX('%[^0-9]%',asdNumNew) - 1 
    ) as int) 

    ELSE 2147483648 
END, 


CASE 
    WHEN ISNUMERIC(asdNumNew)=1 
    THEN NULL 

    WHEN PATINDEX('%[^0-9]%',asdNumNew) > 1 
    THEN SUBSTRING(
     asdNumNew, 
     PATINDEX('%[^0-9]%',asdNumNew) , 
     50 
    ) 

    ELSE asdNumNew 
END 
+0

我明白了!谢谢!我对PATINDEX函数并不了解,现在我已经研究了它,这似乎更容易理解。 – terezzy

0

如果字符串中的所有数字是相当小的,说不超过 10个数字,你 可扩展字符串中的所有数字是准确位数:

123A - > 0000000123A

S4 -> S0000000004 

A3B89 - > A0000000003B0000000089

等,然后对它们进行排序

-- Expand all numbers within S by zeros to be MaxLen 
create function [dbo].ExpandNumbers(@S VarChar(4000), @maxlen integer) returns VarChar(4000) 
as 
begin 
    declare @result VarChar(4000); 
    declare @buffer VarChar(4000); 
    declare @Ch Char; 

    declare @i integer; 

    set @buffer = ''; 
    set @result = ''; 
    set @i = 1; 

    while (@i <= len(@S)) 
    begin 
     set @Ch = substring(@S, @i, 1); 


     if ((@Ch >= '0') and (@Ch <= '9')) 
     set @buffer = @buffer + @Ch 
     else 
     begin 
      if (len(@buffer) > 0) 
      set @result = @result + right(replicate('0', @maxlen) + @buffer, @maxlen); 

      set @buffer = ''; 
      set @result = @result + @Ch; 
     end; 

     set @i = @i + 1; 
    end; 

    if (len(@buffer) > 0) 
    set @result = @result + right(replicate('0', @maxlen) + @buffer, @maxlen); 

    return @result; 
end; 

-- Final query is 

    select * 
    from viewASD 
order by [dbo].ExpandNumbers(asdNumNew) 
0

尝试此
DECLARE @t表(编号为nvarchar(20)) 插入件插入@t 选择 'L010' union all select 'L011' union all select 'L011' union all s选 'L001' UNION ALL选择 'L012' UNION ALL选择 '18'
UNION ALL选择 '8' UNION ALL选择 '17'

union all select 'B004'  
union all SELECT 'B006'  
union all SELECT 'B008' 
union all SELECT 'B018' 
union all SELECT 'UG001' 
union all SELECT 'UG011' 
union all SELECT 'G001'  
union all SELECT 'G002' 
union all SELECT 'G011'  





select * from @t 
order by cast(SUBSTRING(Number, 1, 
case when patindex('%[^0-9]%',Number) > 0 then patindex('%[^0-9]%',Number) - 1 else LEN(Number) end) as int), Number 

O/p

**Number** 
B004 
B006 
B008 
B018 
G001 
G002 
G011 
L001 
L010 
L011 
L011 
L012 
UG001 
UG011 
8 
17 
18 
0

我有类似的东西,但可能会破折号作为主角以及尾随空格。此代码为我工作。

SELECT 
    my_column, 
    PATINDEX('%[^0-9]%',my_column) AS first_alpha_position, 
    CONVERT(INT, 
    CASE 
     WHEN PATINDEX('%[^0-9]%',my_column) = 0 OR PATINDEX('-%',my_column) = 1 
      THEN ABS(my_column) 
     ELSE SUBSTRING(my_column,1,PATINDEX('%[^0-9]%',my_column) -1) 
    END) AS numeric_value, 
    LTRIM(
     SUBSTRING(my_column,PATINDEX('%[^0-9]%',my_column),LEN(my_column)-PATINDEX('%[^0-9]%',my_column)+1) 
) AS alpha_chars 
FROM my_table 
ORDER BY numeric_value,alpha_chars