2011-02-08 19 views
24

Sto cercando di ordinare la colonna di stringhe (contenente i numeri).Ordinamento colonna stringa contenente numeri in SQL?

// SELECT `name` FROM `mytable` ORDER BY `name` ASC 
+----------+ 
+-- name --+ 
+----------+ 
+-- a 1 ---+ 
+-- a 12 --+ 
+-- a 2 ---+ 
+-- a 3 ---+ 

Vedete algoritmo di ordinamento naturale del Mysql sta mettendo a 12 dopo a 1 (che è ok per la maggior parte delle applicazioni), ma non ho particolari esigenze, quindi voglio risultato dovrebbe essere ordinato come questo.

+----------+ 
+-- name --+ 
+----------+ 
+-- a 1 ---+ 
+-- a 2 ---+ 
+-- a 3 ---+ 
+-- a 12 --+ 

E 'possibile con solo SQL, o devo manipolare i set di risultati a livello di applicazione?

+0

è il prefisso alfabetica sempre una lunghezza costante per tutte le righe? –

+0

No, è una stringa normale che viene ripetuta a volte. – Ish

+2

Quindi qualcosa come 'order by left (name, 1), cast (SUBSTRING (name, 2) int)' non funzionerebbe allora. Potete fornire alcuni dati più vari che illustrano le vostre esigenze esatte? –

risposta

36

Andando sul presupposto è sempre WORD_space_NUMBER questo dovrebbe funzionare:

SELECT * 
FROM  table 
ORDER BY CAST(SUBSTRING(column,LOCATE(' ',column)+1) AS SIGNED) 

Usa POSITION per trovare lo spazio, SUBSTRING per afferrare il numero dopo di esso e CAST per renderlo un valore comparabile.

Se c'è un modello diverso per la colonna, fammelo sapere e cercherò di escogitare una soluzione migliore.


EDIT dimostrato di funzionare:

mysql> INSERT INTO t (st) VALUES ('a 1'),('a 12'),('a 6'),('a 11'); 
Query OK, 4 rows affected (0.00 sec) 
Records: 4 Duplicates: 0 Warnings: 0 

mysql> SELECT * FROM t ORDER BY st; 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 4 | a 11 | 
| 2 | a 12 | 
| 3 | a 6 | 
+----+------+ 
4 rows in set (0.00 sec) 

mysql> SELECT * FROM t ORDER BY CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED); 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 3 | a 6 | 
| 4 | a 11 | 
| 2 | a 12 | 
+----+------+ 

mysql> INSERT INTO t (st) VALUES ('b 1'),('b 12'),('b 6'),('b 11'); 
Query OK, 4 rows affected (0.00 sec) 
Records: 4 Duplicates: 0 Warnings: 0 

mysql> SELECT * FROM t ORDER BY CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED); 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 5 | b 1 | 
| 3 | a 6 | 
| 7 | b 6 | 
| 4 | a 11 | 
| 8 | b 11 | 
| 2 | a 12 | 
| 6 | b 12 | 
+----+------+ 
8 rows in set (0.00 sec) 

mysql> SELECT * FROM t ORDER BY LEFT(st,LOCATE(' ',st)), CAST(SUBSTRING(st,LOCATE(' ',st)+1) AS SIGNED); 
+----+------+ 
| id | st | 
+----+------+ 
| 1 | a 1 | 
| 3 | a 6 | 
| 4 | a 11 | 
| 2 | a 12 | 
| 5 | b 1 | 
| 7 | b 6 | 
| 8 | b 11 | 
| 6 | b 12 | 
+----+------+ 
8 rows in set (0.00 sec) 

ignorare i miei nomi tabella/colonna zoppo, ma mi dà il risultato corretto. Inoltre è andato un po 'oltre e ha aggiunto il doppio tipo per rompere il prefisso di lettere con numerico.

Modifica SUBSTRING_INDEX renderà po 'più leggibile.

ORDER BY SUBSTRING_INDEX(st, " ", 1) ASC, CAST(SUBSTRING_INDEX(st, " ", -1) AS SIGNED) 
+0

L'hai capito amico ... grazie mille – Ish

+0

@ish: Nessun problema. Puoi anche aggiungere un 'LEFT (column, LOCATE ('', column))' nell'ordine per raggrupparlo per lettera (e), quindi i numeri. –

+0

grazie per più opzioni :), La tua soluzione originale è servita al mio scopo. E ho imparato a conoscere le abilità di 'CAST' di MySQL ... saluti – Ish

1

Dai un'occhiata alle funzioni di MySQL CAST/Convert.

SELECT name FROM mytable ORDER BY CAST(name AS INTEGER) ASC; 

Edit: ho letto:

Sto cercando di ordinare colonna stringa (numeri che contengono).

... ma basta dare un'occhiata al set di risultati. Anche lo a parte dei contenuti? In tal caso, puoi utilizzare funzioni come MID per estrarre solo il valore numerico e lanciarlo.

Ma se tutti righe contengono solo a senza variazioni, si potrebbe anche ometterlo ...

+0

ottenuto mysql errore 'sintassi corretta da utilizzare vicino a 'INTEGER) ASC LIMIT 0, 30' – Ish

+0

@Ish: A causa della stessa cosa che ho dimenticato. Utilizzare SIGNED/UNSIGNED quando si usa CAST/CONVERT. –

0

Un'altra opzione potrebbe essere quella di riempire la stringa con spazi alla sinistra del numero (ad es.aggiungere spazi tra la parola ed il numero) e utilizzare la stringa risultante selezionare, comething simili:

ORDER BY INSERT(
    column, 
    LOCATE(' ', column), 
    0, 
    SPACES(20 - LENGTH(column) + LOCATE(' ', column)) 
) 

La stringa viene considerata la 'parola seguita da uno spazio (s) seguito dal numero' modello, e si presume che il numero sia non negativo (o sarebbe errato). Lo 20 con hardcoded viene scelto arbitrariamente e si suppone che sia la lunghezza massima possibile della parte numerica della stringa.

0

qui ho trovato un'altra soluzione con seguente query utilizzando Convertire

select * from tablename where columnname like '%a%' order by Convert(smallint,Replace(columnname,'a','')) 
1

Si può provare questo:

ORDER BY CASE 
    WHEN ISNUMERIC(column) THEN cast(column as int) 
    else ascii(column[1,1]) 
end 
Problemi correlati