2013-05-31 17 views
6

sto usando SQL Server, la colonna è una VARCHAR(50) e voglio ordinare in questo modo:colonna di ordinamento VARCHAR con le voci alfanumeriche

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 

Quello che ho finora è:

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 

Ma questa istruzione SQL mette '14 Draft 'subito dopo' 26 '.

Qualcuno potrebbe aiutare? Grazie

risposta

3

La tua dichiarazione WHERE è ... stranamente complessa.

Sembra che si desideri ordinare con cifre numeriche iniziali in ordine intero e quindi ordinare per il resto. Se è così, dovresti farlo come clausole separate, piuttosto che provare a fare tutto in uno. Il problema specifico che stai riscontrando è che stai consentendo solo un numero a una cifra, anziché due o più. (E c'è No such thing as two.)

Ecco la tua correzione, insieme a un SQLFiddle, utilizzando due test di colonne calcolate separate per il tuo ORDER BY. (Si noti che questo assume la parte numerica del asdNumNew si inserisce in un T-SQL int. In caso contrario, sarà necessario regolare la CAST e il valore massimo sul primo 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

Vedo! Grazie! Non sapevo molto della funzione PATINDEX, e ora da quando l'ho esaminata sembra molto più facile da capire. – terezzy

0

Se tutti i numeri all'interno della stringa sono ragionevolmente piccolo, dicono non supera gli 10 cifre, è possibile espandere tutti i numeri nella stringa di essere esattamente 10 cifre:

123A -> 0000000123A

S4 -> S0000000004 

A3B89 -> A0000000003B0000000089

e così via e poi ordinarli

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

PROVATE QUESTO
declare @t table (Numero nvarchar (20)) inserto in @t selezionare 'L010' unione tutti selezionare 'L011' unione tutti selezionare 'L011' unione tutti s eletti 'L001' unione all select 'L012' unione tutto selezionare '18'
sindacali tutte selezionare '8' sindacali all select '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

Avevo qualcosa di simile, ma con la possibilità di trattini come personaggi principali e spazi finali. Questo codice ha funzionato per me.

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