Sante Caserio
pubblicato circa un anno fa

La clausola ORDER BY in MySQL parte 2

La seconda puntata relativa all'ordinamento dei risulati di una query in MySQL con la clausola ORDER BY

Nell'articolo "La clausola ORDER BY in MySQL parte 1", si è trattato ORDER BY più in generale, in quest'articolo si vuole approfondire le varie tipologie di ordinamento, anche quest'articolo proviene dal blog di uno dei moderatori/editori di MySQL italia: "Sante Caserio"

Tipi di ordinamento

Come si sa, esistono almeno due tipi di ordinamento fondamentali: l’ordinamento alfabetico e l’ordinamento numerico. Naturalmente delle stringhe contenente solo cifre possono essere ordinate numericamente, così come dei numeri possono essere ordinati alfabeticamente.
Qual è la differenza? Se si desidera ordinare i numeri 1000 e 2, numericamente l’ordine sarà: 2, 1000, perchè 2 è ovviamente minore di 1000; mentre l’ordinamento alfabetico sarà: 1000, 2, perchè il carattere ‘1′ viene prima del carattere ‘2′.

Ordine alfabetico

Ci sono casi in cui si desidera ordinare alfabeticamente dei numeri. Il motivo più comune (forse l’unico?) è che i numeri formino un codice, che è considerato una stringa. Allora le query SQL dovranno trasformare il dato numerico in stringa e MySQL ci permette di farlo nel modo seguente:

SELECT numero FROM t ORDER BY CONCAT(numero, '')

La funzione CONCAT concatena tra loro più stringhe e restituisce il risultato, che è a sua volta una stringa. Concatenando un qualsiasi dato con una stringa vuota non lo si altera, ma il risultato è una stringa. Pertanto, nell’esempio, numero sarà ordinato alfabeticamente.
Un altro esempio può essere:

1SELECT CONCAT(int1, int2) AS i FROM t ORDER BY i

Si tenga comunque presente che, se uno dei parametri passati a CONCAT è NULL, il risultato sarà anch’esso NULL. I valori NULL vengono sempre per primi.

Ordine numerico

E’ possibile ordinare numericamente delle stringhe. Il metodo per farlo si basa sullo stesso concetto appena esposto, cioè:

1SELECT codice + 0 AS c FROM t ORDER BY c

Aggiungendo 0 a codice non si modifica il suo valore, ma se era una stringa il risultato c sarà necessariamente un numero, in quanto il risultato di un’addizione non può essere altro che un numero.
Questo è utile anche nel caso in cui alcuni numeri vengano concatenati tra loro come se fossero delle stringhe per ottenere un codice:

1SELECT CONCAT(int1, int2, int3) + 0 AS codice ORDER BY codice

Lo stesso risultato si può ottenere agendo sui valori booleani, che corrispondono numericamente a 0 (falso) e 1 (vero):

1SELECT CONCAT(bool1, bool2, int1) + 0 AS codice ORDER BY codice

Ordinamento booleano

Questo è il tipo di ordinamento che offre i risvolti più interessanti. Non si tratta per forza di ordinare campi booleani: l’ordinamento può essere effettuato su una qualsiasi espressione. Di conseguenza, se si desidera che i primi record siano quelli in cui i campi a e b sono uguali, si può usare una delle seguenti query:

1SELECT * FROM x  ORDER BY (a=b) DESC
2SELECT * FROM x  ORDER BY (a<>b)

Bisogna infatti ricordare che il valore false (0) viene prima di true (1). Questo aspetto in questi casi può trarre in inganno.

Non è il caso di dilungarsi qui sulle infinite possibilità dell’ordinamento booleano, ma ecco una rapida rassegna di esempi:

  • Prima i non-NULL (l’equivalente del NULLS LAST di Oracle): ORDER BY (int IS NOT NULL)
  • Prima i numeri pari: ORDER BY ((int1 MOD 2)>0)
  • ecc ecc
  • Prima le stringhe non vuote: ORDER BY LENGTH(i1)=0
  • Oppure, più ottimizzato: ORDER BY (int1 & 1)

In generale, le espressioni che si possono utilizzare nella WHERE, che sono booleane, si possono utilizzare anche nella ORDER BY.
Ordinamento casuale

Se non si è già letto il precedente articolo sull’ordinamento casuale si consiglia di leggerlo. Qui si intende solo aggiungere che in alcuni casi è possibile ottimizzarlo. Ordinare in base alla funzione rnd(), infatti, è efficiente sulle tabelle di piccole dimensioni, cioè aventi poche righe. Ma con le tabelle aventi molte righe, il costo di questa operazione cresce esponenzialmente con il numero delle righe.

Se ad ogni query abbiamo bisogno che l’ordine sia differente, non c’è niente da fare: dobbiamo usare rand(). Sarebbe inutile, inoltre, prelevare un grande numero di righe con una query, farla passare attraverso una rete (anche locale) e poi ordinarle da programma. Oltre ai ritardi dovuti all’estrazione e alla trasmissione di un grosso numero di righe, si creerebbe traffico inutile.

C’è però qualche caso in cui si vuole semplicemente che le righe siano “sparpagliate”, non che ad ogni estrazione seguano un ordine differente. Allora si può semplicemente aggiungere un campo alla tabella, avente un valore casuale:

1ALTER TABLE t ADD COLUMN r INTEGER UNSIGNED DEFAULT NULL

Tutto sarebbe più semplice se MySQL, come la maggior parte dei suoi concorrenti, permettesse di assegnare come valore di default un’espressione SQL. Chi utilizza DBMS che consentono questo, come PostgreSQL e Firebird, può usare la seguente query:

1ALTER TABLE t ADD COLUMN r INTEGER UNSIGNED DEFAULT rand()

Chi usa MySQL, invece, dovrà assegnare un valore casuale manualmente:

1UPDATE t SET r=rand()

Quando nuovi record vengono inseriti, occorre inserire esplicitamente il valore casuale in r. Se questo non è possibile (perchè ci sono già molti programmi che utilizzano quel db e noi non possiamo o non vogliamo modificarli tutti) si può assegnare il valore casuale ai nuovi record periodicamente:

1UPDATE t SET r=rand() WHERE r IS NUL
L

Inoltre, se di tanto in tanto si desidera modificare l’ordinamento, è sufficiente eseguire periodicamente la prima query (è l’unica operazione di manutenzione dei valori casuali necessaria per gli utenti di PostgreSQL, Firebird, ecc):

1UPDATE t SET r=rand()

Condividi su:

Esprimi un voto:

  • Current rating: 5.0/5
  • 1
  • 2
  • 3
  • 4
  • 5

Argomenti chiave:

Ultimi commenti Ultimi commenti

Esegui il Login oppure registrati per scrivere un commento.
Cerca nel sito...
Ultime recipes

Un utilissimo tool di shell che effettua un dettagliato e comodo report su MySQL MySQL Report un tool di shell per tenere tutto sotto controllo

Un utilissimo tool di shell che effettua un dettagliato e comodo report su MySQL


Vai alla recipe

Un utilissimo tool per sniffare il traffico Client/Server TCP/IP di MySQL MySQLSniffer sniffare il traffico TCP di MySQL

Un utilissimo tool per sniffare il traffico Client/Server TCP/IP di MySQL


Vai alla recipe

Verificare l'integrità, riparare gestire chiavi e memoria di tabelle MyISAM attraverso myisamchk riparare file MyISAM

Verificare l'integrità, riparare gestire chiavi e memoria di tabelle MyISAM attraverso il file myisamchk


Vai alla recipe

Un tool per comprimere le tabelle MyISAM fino a oltre il 50% myisampack comprimere file MyISAM

Un tool per comprimere le tabelle MyISAM fino a oltre il 50%


Vai alla recipe

mysqlshow le info di base sui database, tabelle e colonne senza utilizzare alcun mysqlshow visualizzare le informazioni sul database MySQL

mysqlshow le info di base sui database, tabelle e colonne senza utilizzare alcun client


Vai alla recipe

Utilizzando UNION / UNION ALL su campi int unsigned zerofill,
ho notato che MysqlUNION / UNION ALL su campi int unsigned zerofill. di DebUsr
Vai al tip

Utilizzo di funzioni come alias di campo tramite l'impiego di prepared statementReport con alias di campo dinamici di john_revelator
Vai al tip

Può capitare che sia necessario eseguire un dump di database in formato Comma SeparatedEsecuzione dump in formato CSV (tabelle in engine MyIsam esportate in formato CSV) di ghigomatto
Vai al tip

E' possibile eseguire le query SQL contenute in un file di testo. Questo è utileEseguire le query da un file di testo di Sante Caserio
Vai al tip

Se vogliamo fare il backup di tutti i database con mysqldump, e ne abbiamo parecchiFare il backup di tutti i database di Sante Caserio
Vai al tip

Salve,vorrei chiedervi un aiutino per una query che mi infastidisce un pò.
Ho 4 aiuto per una query! di fighterdorico Vai al topic

Salve,vorrei chiedervi un aiutino per una query che mi infastidisce un pò.
Ho 4 aiuto per una query! di fighterdorico Vai al topic

Salve,vorrei chiedervi un aiutino per una query che mi infastidisce un pò.
Ho 4 aiuto per una query! di fighterdorico Vai al topic

Salve a tutti.

Ho una tabella con lettere accentate.
Le lettere vengono visualizzate ordinamento tabelle di ditch Vai al topic

Salve a tutti.

Ho una tabella con lettere accentate.
Le lettere vengono visualizzate ordinamento tabelle di ditch Vai al topic