SQL per l'ordinamento per numero - 1,2,3,4 ecc invece di 1,10,11,12


87

Sto tentando di ordinare in base a una colonna numerica nel mio database che ha valori 1-999

Quando uso

ORDER_BY registration_no ASC

Ottengo….

1
101
102
103
104
105
106
107
108
109
11
110
Etc…

Quindi sembra ordinare in base alla prima cifra in contrasto con il numero.

Qualcuno sa quale SQL usare se voglio ordinarlo in base al valore? Quindi 1,2,3,4,5,6ecc


11
La tua colonna è di tipo varchar a causa del quale stai affrontando questo comportamento.
Meherzad

qual è il tipo di dati della colonna registration_no?
Praveen Prasannan

9
Usa order by registration_no + 0 ascper risolvere il tuo problema.
Meherzad

10
Non si dovrebbero mai memorizzare numeri in una colonna di caratteri. Il tuo problema è il risultato diretto di quell'errore.
a_horse_with_no_name

1
La mia colonna è Varchar ei dati che memorizzo sono Classe 10 / Classe 9 / Classe 8. Ora la classe 10 viene prima della classe 8. Come risolvo questo problema senza dover fare per una colonna display_order?
Vishnoo Rath

Risposte:


142

Un modo per ordinare per numeri interi positivi, quando sono memorizzati come varchar, è ordinare prima in base alla lunghezza e poi al valore:

order by len(registration_no), registration_no

Ciò è particolarmente utile quando la colonna potrebbe contenere valori non numerici.

Nota: in alcuni database, potrebbe essere chiamata la funzione per ottenere la lunghezza di una stringa length()invece di len().


1
Questo non funzionerà in tutti i casi. Fuori dalla testa, i casi che non funzionano sono miscele di numeri interi con; numeri negativi, numeri con zeri iniziali, numeri con frazioni e parole e numeri combinati.
WonderWorker

10
@ Knickerless-Noggins. . . Leggi la prima frase della risposta. Penso che sia abbastanza chiaro.
Gordon Linoff

@GordonLinoff ordina due volte in base alla stessa colonna non richiede CPU e memoria?
loneStar

@ Achyuth. . . Il numero di tasti in una order byha un effetto minimo sulle prestazioni.
Gordon Linoff

1
Per Oracle SQL, usa length()invece dilen()
Stevoisiak

62
ORDER_BY cast(registration_no as unsigned) ASC

converte esplicitamente il valore in un numero. Un'altra possibilità per ottenere lo stesso sarebbe

ORDER_BY registration_no + 0 ASC

che forzerà una conversazione implicita.

In realtà dovresti controllare la definizione della tabella e cambiarla. È possibile modificare il tipo di dati inint questo modo

ALTER TABLE your_table MODIFY COLUMN registration_no int;

13

Se utilizzi SQL Server:

ORDER_BY cast(registration_no as int) ASC

4
ORDER_BY cast(registration_no as unsigned) ASC

fornisce il risultato desiderato con avvertenze.

Quindi, meglio andare

ORDER_BY registration_no + 0 ASC

per un risultato pulito senza avvisi SQL.


Puoi spiegare perché fare + 0lavori? L'ho testato sul mio set di dati e, in effetti, funziona, ma sono curioso perché? Lo converte in un numero prima di ordinare?
Joshua Pinter

2

Presumo che il tipo di colonna sia STRING (CHAR, VARCHAR, ecc.) E la procedura di ordinamento lo ordina come una stringa. Quello che devi fare è convertire il valore in valore numerico. Come farlo dipenderà dal sistema SQL che utilizzi.


1

A volte semplicemente non hai scelta di dover memorizzare numeri mescolati con il testo. In una delle nostre applicazioni, l'host del sito Web che utilizziamo per il nostro sito di e-commerce crea filtri dinamicamente fuori dagli elenchi. Non è possibile ordinare in base a qualsiasi campo tranne il testo visualizzato. Quando volevamo che i filtri costruissero un elenco che dicesse cose come da 2 "a 8" da 9 "a 12" da 13 "a 15" ecc., Ne avevamo bisogno per ordinare 2-9-13, non 13-2-9 come farà quando leggere i valori numerici. Quindi ho usato la funzione di replica di SQL Server insieme alla lunghezza del numero più lungo per riempire qualsiasi numero più corto con uno spazio iniziale. Ora 20 viene ordinato dopo 3 e così via.

Lavoravo con una vista che mi dava le lunghezze minime e massime, le larghezze, ecc. Per il tipo e la classe dell'elemento, ed ecco un esempio di come ho scritto il testo. (LB n Low e LB n High sono le estremità inferiore e superiore delle 5 parentesi di lunghezza.)

REPLICATE(' ', LEN(LB5Low) - LEN(LB1High)) + CONVERT(NVARCHAR(4), LB1High) + '" and Under' AS L1Text,
REPLICATE(' ', LEN(LB5Low) - LEN(LB2Low)) + CONVERT(NVARCHAR(4), LB2Low) + '" to ' + CONVERT(NVARCHAR(4), LB2High) + '"' AS L2Text,
REPLICATE(' ', LEN(LB5Low) - LEN(LB3Low)) + CONVERT(NVARCHAR(4), LB3Low) + '" to ' + CONVERT(NVARCHAR(4), LB3High) + '"' AS L3Text,
REPLICATE(' ', LEN(LB5Low) - LEN(LB4Low)) + CONVERT(NVARCHAR(4), LB4Low) + '" to ' + CONVERT(NVARCHAR(4), LB4High) + '"' AS L4Text,
CONVERT(NVARCHAR(4), LB5Low) + '" and Over' AS L5Text

1

Preferisco fare un "PAD" ai dati. MySql lo chiama LPAD, ma puoi lavorare per fare la stessa cosa in SQL Server.

ORDER BY  REPLACE(STR(ColName, 3), SPACE(1), '0') 

Questa formula fornirà zeri iniziali in base alla lunghezza della colonna pari a 3. Questa funzionalità è molto utile in altre situazioni al di fuori di ORDER BY, quindi è per questo che ho voluto fornire questa opzione.

Risultati: 1 diventa 001 e 10 diventa 010, mentre 100 rimane lo stesso.


0

Questo problema è solo perché hai dichiarato la colonna nel tipo di dati CHAR, VARCHAR o TEXT. Basta cambiare il tipo di dati in INT, BIGINT ecc. Questo risolverà il problema del tuo ordine personalizzato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.