2012-03-26 1 views
8

Per impostazione predefinita, i numeri di ordini SQL prima dei caratteri.ORDINA DI varchar con [a-9] anziché [0-Z] in SQL

Quindi, se ho la colonna "nome":

abc 
ab1 
a1b 
1ba 
1bac 
b21 

Dal tipo SQL da 0-Z (prima 0-9, poi AZ), la query

SELECT * FROM ... ORDER BY name 

si tradurrà in :

1ba 
1bac 
a1b 
ab1 
abc 
abc1 
b21 

Ma voglio che venga ordinato da a-0 (prima aZ, quindi 0-9).

abc 
abc1 
ab1 
a1b 
b21 
1ba 
1bac 

Come si esegue questa operazione in una query? Più specificamente, come faccio a farlo in SQLite?

ho trovato una soluzione in Sort MySQL results alphabetically, but with numbers last, ma solo per il primo carattere.

+0

I tuoi valori sono sempre lunghi 3 caratteri? – gbn

+0

Potresti [usare l'interfaccia C per creare una funzione] (http://www.sqlite.org/c3ref/create_function.html) che usa ['regexp'] (http://sqlite.org/lang_expr.html) operatore per tirare fuori le lettere e i numeri in colonne separate. –

+0

@gbn No, possono essere molto lunghi .. Probabilmente hanno dimostrato che :) – Nic

risposta

0

Questa è la mia idea: si aggiunge un altro "help_column" che controlla se il primo carattere è un numero e assegnare 1 ad esso, altrimenti assegna 0 e poi ordinare da questa colonna e poi per nome:

select *, case 
      when substring(name,1,1) like '[0-9]' then 1 
      else 0 
      end as help_order 
from (
select 'ab1' as name union select 'a1b' as name union select '1ba' as name union select 'b21' as name 
) a 
order by help_order, name 

Ovviamente, potrebbe essere necessario migliorare l'espressione regolare [0-9] per trattare più di un numero, se necessario.

E, naturalmente, è necessario sostituire la query interna (quella con diversi sindacati con la tabella).

+0

Questo funzionerà solo per il primo personaggio (ho fatto lo stesso errore al primo tentativo) –

1

di prova con questi dati piacere

declare @t table(a char(3)) 
insert @t values('ab1') 
insert @t values('a1b') 
insert @t values('1ba') 
insert @t values('b21') 
insert @t values('12a') 
insert @t values('13b') 


select a, 
patindex('[0-9]%', a + 'a'), 
patindex('_[0-9]%', a + 'a'), 
patindex('__[0-9]%', a + 'a') 
from @t order by 2, 3, 4, 1 

o

select a 
from 
(select a, 
patindex('[0-9]%', a + 'a') b, 
patindex('_[0-9]%', a + 'a') c, 
patindex('__[0-9]%', a + 'a') d 
from @t) e 
order by b, c, d, a 
+4

Non credo che questo sia valido SQLite sintassi. –

3

Vorrei suggerire SELECT ing un'altra colonna, dicono name_replace, con le cifre sostituiti da un carattere high-ASCII (come ~) , quindi ordinando su quella colonna quindi sul nome. Purtroppo SQLite non ha il supporto per regular expression sostituire:

SELECT name, replace(... replace(replace(name, '0', '~'), '1', '~') ... '9', '~') AS name_replace 
    FROM mytable 
ORDER BY name_replace, name 

Le cifre verranno scorso, quando l'ordinamento su name_replace. L'ordinamento su name verrà quindi ordinato in base alle cifre.

0

Thsi sostituisce da 0-9 a sopra ASCII 122 (che è in minuscolo z).

SqlLite non ha una funzione CHAR per fare la sostituzione con codice di carattere (es CHAR(123) a CHAR(132)) che può essere necessario invece del mio CHAR (123) tentare

testato ovviamente :-)

ORDER BY 
    REPLACE 
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(name, '0', '{0') 
    , '1', '{2') 
    , '2', '{2') 
    , '3', '{3') 
    , '4', '{4') 
    , '5', '{5') 
    , '6', '{6') 
    , '7', '{7') 
    , '8', '{8') 
    , '9', '{9') 

Edit: anche se, la soluzione di @ David Faber fa lo stesso ma un po 'più semplice ...

2

Questo fa il trucco con i dati forniti.

SELECT * 
FROM Table 
ORDER BY Name COLLATE SQL_EBCDIC037_CP1_CS_AS 

Tuttavia si consiglia di esaminare i vari tipi di fascicolazione per assicurarsi che faccia ciò che si desidera su tutta la linea.

AGGIORNAMENTO: Lei ha citato SQLite ma l'ho provato su MSSQL. Non sono sicuro se queste regole di confronto siano disponibili in SQLite ma i commenti riportati di seguito potrebbero contenere informazioni utili.

+1

OP in realtà ha menzionato SQLite, ma questo potrebbe funzionare - non so se esiste una sequenza di confronto esistente in SQLite che farebbe il trucco, tuttavia - potrebbe essere necessario crearne uno. –

+0

come @DavidFaber ha sottolineato, la piattaforma di destinazione effettiva è SQLite. Ho trovato http://sqlite.org/datatype3.html Ma non riesco davvero a capire se questa soluzione sia fattibile in SQLite. – Nic

+0

Ho aggiornato la mia risposta di conseguenza, grazie –