2013-05-31 10 views
6

używam programu SQL Server, kolumna jest VARCHAR(50) i chcę rozwiązać to tak:Sortowanie VARCHAR kolumna z wpisami alfanumerycznych

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 

Co mam tak daleko jest:

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 

Ale to wyrażenie SQL umieszcza "14 Draft" zaraz po "26".

Czy ktoś może pomóc? Dzięki

Odpowiedz

3

Twoje zdanie WHERE jest ... dziwnie skomplikowane.

Wygląda na to, że chcesz sortować według dowolnej cyfry wiodącej w porządku całkowitym, a następnie sortować według pozostałej części. Jeśli tak, powinieneś zrobić to jako oddzielne zdania, zamiast próbować zrobić wszystko w jednym. Problem polega na tym, że dopuszczasz tylko liczbę jednocyfrową zamiast dwóch lub więcej. (I tam jest No such thing as two.)

Oto twoja poprawka, wraz z SQLFiddle, używając dwóch oddzielnych testów kolumn obliczeniowych dla Twojego ORDER BY. (Zauważ, że ten zakłada, że ​​część numeryczna asdNumNew zmieści się w T-SQL int. Jeśli nie, trzeba będzie dostosować obsady i maksymalną wartość na pierwszym indziej.)

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

Rozumiem! Dziękuję Ci! Nie wiedziałem zbyt wiele o funkcji PATINDEX, a teraz, odkąd się zajrzałem, wydaje się o wiele łatwiejsze do zrozumienia. – terezzy

0

przypadku wszystkich numerów w całym łańcuchu są dość małe, powiedzmy nieprzekraczającej 10 cyfr, można rozwinąć wszystkie numery w ciągu być dokładnie 10 cyfr:

123A -> 0000000123A

S4 -> S0000000004 

A3B89 -> A0000000003B0000000089

i tak dalej, a następnie posortować je

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

Try This
stwierdzenie stołowego @t (numer nvarchar (20)) wkładka do @t wybrać 'L010' połączenie wszystkie wybierz 'L011' połączenie wszystkie wybierz 'L011' połączenie wszystkie s elekt 'L001' związek wszystkim wybrać 'L012' związek wszystkim wybrać '18'
związków wszystkie wybrać '8' związków wszystkim wybrać '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

Miałem coś podobnego, ale z możliwością pojawienia się kresek jako znaków wiodących, a także końcowych spacji. Ten kod pracował dla mnie.

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 
Powiązane problemy