Newsgroup: it.comp.software.database
Titolo: Mysql 4 query impossibile?

Ho una tabella in un db mysql4 che ha la seguente struttura:
id(int) -------- myfield(varchar)
1 --------- |number1|number2|
2 --------- |number1|
3 --------- |number1|number2|number3|
4 --------- |number1|number2|number3|number4|
e cosi via...
E' possibile, con una query sola (purtroppo mysql4 non ha udf...) ordinare i
risultati in base a quanti pipe (|) ci sono nel campo myfield?
Grazie dell'attenzione.
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/


Non e' impossibile, anche se la soluzione e' orribile a vedersi. Ma con gli scarsi mezzi
a disposizione della versione 4 non c'e' tanto. Se il campo myfield e' composto da numeri
separati da pipe, ecco una soluzione brutta ma funzionante.
select * from mytable;
+----+-------------------+
| id | myfield           |
+----+-------------------+
|  1 | 10|1|12|9         |
|  2 | 1|2               |
|  3 | 19|5|59|91        |
|  4 | 111|31|10|1|12|9  |
|  5 | 1|2|7             |
|  6 | 95|59|91          |
|  7 | 123456789|2000000 |
+----+-------------------+
select id, myfield,
replace(
 replace(
  replace(
   replace(
    replace(
     replace(
      replace(
       replace(
        replace(
         replace(myfield,
         '9',''),
        '8',''),
       '7',''),
      '6',''),
     '5',''),
    '4',''),
   '3',''),
  '2',''),
 '1',''),
'0','') as so
from mytable
order by so;
+----+-------------------+-------+
| id | myfield           | so    |
+----+-------------------+-------+
|  2 | 1|2               | |     |
|  7 | 123456789|2000000 | |     |
|  5 | 1|2|7             | ||    |
|  6 | 95|59|91          | ||    |
|  1 | 10|1|12|9         | |||   |
|  3 | 19|5|59|91        | |||   |
|  4 | 111|31|10|1|12|9  | ||||| |
+----+-------------------+-------+
select id, myfield,
replace(
 replace(
  replace(
   replace(
    replace(
     replace(
      replace(
       replace(
        replace(
         replace(myfield,
         '9',''),
        '8',''),
       '7',''),
      '6',''),
     '5',''),
    '4',''),
   '3',''),
  '2',''),
 '1',''),
'0','') as so
from mytable
order by so DESC;
+----+-------------------+-------+
| id | myfield           | so    |
+----+-------------------+-------+
|  4 | 111|31|10|1|12|9  | ||||| |
|  1 | 10|1|12|9         | |||   |
|  3 | 19|5|59|91        | |||   |
|  5 | 1|2|7             | ||    |
|  6 | 95|59|91          | ||    |
|  2 | 1|2               | |     |
|  7 | 123456789|2000000 | |     |
+----+-------------------+-------+
Puoi anche omettere il campo di ordinamento dalla visualizzazione
select * from mytable
order by
replace(
 replace(
  replace(
   replace(
    replace(
     replace(
      replace(
       replace(
        replace(
         replace(myfield,
         '9',''),
        '8',''),
       '7',''),
      '6',''),
     '5',''),
    '4',''),
   '3',''),
  '2',''),
 '1',''),
'0','');
----+-------------------+
| id | myfield           |
+----+-------------------+
|  2 | 1|2               |
|  7 | 123456789|2000000 |
|  5 | 1|2|7             |
|  6 | 95|59|91          |
|  1 | 10|1|12|9         |
|  3 | 19|5|59|91        |
|  4 | 111|31|10|1|12|9  |
+----+-------------------+
ciao
gmax
-- 
 _  _ _  _
(_|| | |(_|><  The Data Charmer
 _|
http://datacharmer.org/

 3 --------- |treni|vagoni|camini|
e cosi via
non c'è nessuna relazione logica tra ciò che è contenuto tra i pipe...:-(((
Dici che non c'è cmq via d'uscita?
Grazie.


Il 27 Lug 2006, 12:16, Giuseppe Maxia <gmax_@_cpan_._org> ha scritto:
[CUT]
Penso di averti fuorviato.
Tra i pipe non sono numeri ma stringhe di lunghezza variabile.
Dici che non c'è cmq soluzione?
Thx



Tecnicamente, si potrebbe ampliare la soluzione vista per i numeri, e
nidificare 36 istruzioni REPLACE per avere la stessa soluzione.
Ma il fatto che tu ti trovi ad avere questo problema dovrebbe farti riflettere
sulla struttura dei tuoi dati. Il problema esiste perche' i dati non sono
normalizzati. Il non raggiungimento della prima forma normale porta a
questi eccessi.
La soluzione corretta e' scomporre la colonna myfield e trasformarla in una tabella
quindi avrai:
mytable
ID    id_contenuto
CONTENUTI
id_contenuto, valore
Le tre righe di cui sopra verrebbero trasformate cosi:
CONTENUTI
1  ruote in lega
2  macchine gialle
3  case in affitto
4  treni
5  vagoni
6  camini
mytable
ID id_contenuto
1  1
1  2
2  3
3  4
3  5
3  6
in questo modo, l'ordinamento per conteggio viene naturale:
SELECT id, count(*) as quanti
from mytable inner join contenuti using (id_contenuto)
group by id
order by quanti


 Dici che non c'è cmq via d'uscita?
Rimboccarsi le maniche e ristrutturare il db...


In effetti, una soluzione migliore (e piu' semplice) esiste:
select id, length(myfield) - length(replace(myfield,'|','')) as numpipes
from mytable
order by so;
Ma le mie considerazioni sulla struttura restano valide.
