Skip to content

Come impazzire con MySQL

11 aprile 2008

logo MySQL

Ma esiste una locate che cerchi da destra? Perché io sono impazzito…

Nel DB di http://elezioni.softwarelibero.it/ ci sono i dati relativi ai candidati.

La tabella è strutturata così:

CREATE TABLE candidato (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nome VARCHAR(150) NOT NULL UNIQUE,
    accetta TINYINT,
    email VARCHAR(150),
    telefono VARCHAR(20),
    data DATETIME,
    partito_id INT
);

Perché c’è il campo nome e non ho messo nome e cognome?

Sarebbe piaciuto molto anche a me, però dovevo fare il parsing dei dati dai dati forniti dal Ministero dell’Interno.

Se andate a vedere i file che il Ministero pubblica (sotto “Politiche: le liste ammesse”) noterete che i il nome e il cognome dei candidati sono inseriti nella stessa cella, discernere l’uno (il nome) dall’altro (il cognome) non è cosa semplice: non tutti si chiamano Paolo Rossi, c’è chi si chiama Paolo Alberto Rossi, Paolo Dei Rossi, Paolo De’ Rossi detto Pinuccio, fare il parsing non è una cosa facile.

Visti i tempi stretti ho semplicemente “buttato” i dati nel DB così, nudi e crudi. Questa semplificazione iniziale però l’ho pagata dopo.

Ed ecco qua cosa ho pagato: per il comunicato (una tantum) i dati dovevo tirarmeli fuori nel formato Cognome Nome (mentre erano dentro come Nome Cognome), la cosa era un pochino complicata, ma ecco una soluzione approssimata: prendo il token più a destra dal campo nome e lo metto a sinistra.

Era necessario quindi selezionare lo spazio più a destra e rompere la stringa in quel punto. Facile. Il problema era farlo con le funzioni sulle stringhe di MySQL e, a meno che non mi sia perso qualcosa, l’unico modo che ho trovato era usare la funzione locate che, come ho detto all’inizio inizia a cercare una sottostringa da sinistra.

Be’ , ecco l’orrida query che ho fatto, me ne vergogno un po’ devo ammettere, infatti chiedo a qualche SQL hacker se mi risolve la situazione con qualcosa di più elegante : ). Ah sì ecco qua il mostro, aspe’ che apro la gabbia:

select concat(
  reverse(
    left(reverse(nome), locate(' ',reverse(nome)))
  ),
  ' ',
  reverse(
    substring(reverse(nome),locate(' ',reverse(nome)))
  )
) as il_nome
from candidato
where accetta=1
order by il_nome

Il workaround consiste nel considerare la stringa “invertita”, quindi cercare l’ultimo spazio su Paolo Alberto Rossi (cosa non possibile solo con locate) equivale a trovare il primo su issoR otreblA oloaP.

Cosa ne pensate? Non è proprio una raffinata soluzione no?

From → computer

3 commenti
  1. ferenir permalink

    Ciao. :)

    All’inizio hai scritto “noterete che i il nome e il cognome dei candidati sono inseriti nella stessa cella, discernere l’uno (il nome) dall’altro (il cognome) non è cosa semplice: non tutti si chiamano Paolo Rossi, c’è chi si chiama Paolo Alberto Rossi, Paolo Dei Rossi, Paolo De’ Rossi detto Pinuccio, fare il parsing non è una cosa facile.”

    Poi però giustamente ti trovi costretto a fare il parsing del cognome in query.

    Visto che hai trovato un metodo per distinguere tra “nome” e “cognome” e che già lo utilizzi in query, perché non creare un campo “cognome” in tabella e far partire uno script che ti separa nomi e cognomi assegnandoli ai singoli campi?

    Così l’orrida query, come la chiami tu – a me piace :) – non serve più.

    Oppure estrarre la stringa nome per intero e una volta fuori “spezzarla” come desideri recuperando solo il presunto cognome, ad esempio.

    Voglio dire: ma sei costretto a lavorare i dati che estrai dal db direttamente in query?

  2. vrde permalink

    ciao ferenir, grazie per il prezioso commento.

    piccola premessa: nel db, oltre ai 101 candidati che hanno aderito all’iniziativa, ce ne sono circa altri 280 (tra leader del partito e candidati delle circoscrizioni estere, non sono però tutti i candidati di tutte le circoscrizioni).

    Usare il metodo descritto per normalizzare tutti i circa 380 record avrebbe preso molto tempo perché avrei dovuto controllare tupla per tupla.

    Comunque una funzione di normalizzazione sarebbe stata la cosa migliore da fare, sono perfettamente d’accordo con te : )
    La funzione comunque doveva essere un po’ più intelligente di “considero l’ultimo token come cognome” e avrebbe preso sicuramente più tempo dei circa 5 minuti necessari a estrapolare i dati relativi ai candidati aderenti (con il presunto cognome all’inizio) e sistemarli a mano.

    Visto che questi 5 minuti erano necessari una o due volte al massimo ho preferito la soluzione scimmia : D (ripeto, sistemare anche le altre 280 tuple era sicuramente l’idea più corretta ma putroppo richiedeva tempo extra – che non avevo).

    Ah anche estrarre di dati e modificarli da qualche linguaggio di programmazione era una buona idea ma, non so, farlo con MySQL era diventata ormai una sfida a cui non potevo rinunciare, so che mi capisci : P

  3. ferenir permalink

    “farlo con MySQL era diventata ormai una sfida a cui non potevo rinunciare, so che mi capisci : P”

    Si! Ti capisco benissimo. :D

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger cliccano Mi Piace per questo: