2012-02-18 9 views
5

Sto lavorando con un ampio set di dati legacy (convertiti da un file flat db), in cui un campo è formattato come le ultime 2 cifre dell'anno il record è stato inserito, seguito da un incremento di 4 cifre ...MySQL - creazione di una funzione definita dall'utente per un ordinamento personalizzato

ad esempio, il terzo record creato nel 1998 sarebbe "980003" e l'undicesimo record creato nel 2004 sarebbe "040011".

Non posso modificare questi valori - esistono attraverso la loro azienda, sono registrati con lo stato, i clienti, ecc. So che sarebbe bello separare l'anno e il resto in colonne separate, ma questo è non possibile. non posso nemmeno farlo "internamente" perché ogni riga ha circa 300 campi che sono tutti ordinabili e sono molto abituati a lavorare con questo campo come identificatore di record.

quindi sto cercando di implementare un UDF MySQL (per la prima volta) per ordinare. La query viene eseguita correttamente e mi permette di "selezionare qualsiasi cosa dall'ordine di una tabella da custom_sort (qualunque cosa)", ma l'ordine non è quello che mi aspetterei.

Ecco quello che sto usando:

DELIMITER // 

CREATE FUNCTION custom_sort(id VARCHAR(8)) 
    RETURNS INT 
    READS SQL DATA 
    DETERMINISTIC 
    BEGIN 
     DECLARE year VARCHAR(2); 
     DECLARE balance VARCHAR(6); 
     DECLARE stringValue VARCHAR(8); 
     SET year = SUBSTRING(0, 2, id); 
     SET balance = SUBSTRING(2, 6, id); 
     IF(year <= 96) THEN 
      SET stringValue = CONCAT('20', year, balance); 
     ELSE 
      SET stringValue = CONCAT('19', year, balance); 
     END IF; 
     RETURN CAST(stringValue as UNSIGNED); 
    END// 

I record solo tornare a 96 (quindi l'arbitraria "se primi 2 caratteri sono meno di 96, anteporre '20' in caso contrario anteporre '19'). Non ne sono entusiasta, ma non credo che sia il problema principale.

Per lanciare un'altra chiave nelle opere, risulta che 1996 e 1997 sono entrambe a 5 cifre, seguendo lo stesso schema descritto sopra ma invece di un incremento di 4 cifre, è un incremento di 3 cifre. Ancora una volta, ho il sospetto che questo sarà un problema, ma non è il problema principale

Un esempio dei rendimenti che sto ottenendo con questo Custom_Sort:

001471 
051047 
080628 
040285 
110877 
020867 
090744 
001537 
051111 
080692 
040349 
110941 
020931 
090808 
001603 
051175 

davvero non ho idea di cosa sto facendo qui e non ho mai usato MySQL per un'UDF come questo - qualsiasi aiuto sarebbe apprezzato .

TYIA

/EDIT errore di battitura

/EDIT 2 concat necessario "anno" Valore aggiunto - ancora ottenere gli stessi risultati

+0

In che modo MySQL sa che si sta eseguendo il cast di un 'UNSIGNED INT', e non per esempio' UNSIGNED TINYINT'? Lo sa, o assume qualche tipo numerico predefinito? – biziclop

+0

non ne ho idea :) – momo

+0

Non è possibile aggiungere una nuova colonna al db con i valori fissi? Ad ogni modo, per il diverso problema di lunghezza del numero, è possibile utilizzare la funzione 'LPAD': http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_lpad – biziclop

risposta

5

avete alcuni problemi con i vostri sottostringhe, e il cast a int al fine consente di ordinare i valori con più cifre alla fine, non per anno. Questo dovrebbe funzionare meglio;

DELIMITER // 

CREATE FUNCTION custom_sort(id VARCHAR(8)) 
    RETURNS VARCHAR(10) 
    READS SQL DATA 
    DETERMINISTIC 
    BEGIN 
     DECLARE year VARCHAR(2); 
     DECLARE balance VARCHAR(6); 
     DECLARE stringValue VARCHAR(10); 
     SET year = SUBSTRING(id, 1, 2); 
     SET balance = SUBSTRING(id, 3, 6); 
     IF(year <= 96) THEN 
      SET stringValue = CONCAT('20', year, balance); 
     ELSE 
      SET stringValue = CONCAT('19', year, balance); 
     END IF; 
     RETURN stringValue; 
    END// 

DELIMITER ; 

Questo può essere semplificato un po a;

DELIMITER // 

CREATE FUNCTION custom_sort(id VARCHAR(8)) 
    RETURNS varchar(10) 
    DETERMINISTIC 
    BEGIN 
     IF(SUBSTRING(id, 1, 2) <= '96') THEN 
      RETURN CONCAT('20', id); 
     ELSE 
      RETURN CONCAT('19', id); 
     END IF; 
    END// 

DELIMITER ; 
+0

in questo momento ... – momo

+0

molto più vicino!ma penso che il 5 cifre contro 6 cifre sia un problema (ed è per questo che stavo cercando di trasmettere a INT) ... se ordino ASC ottengo 97001, 97002, 97003, se ordino DESC ottengo 96323, 96322, 96321. il "primo" record dovrebbe probabilmente essere 96something, e "last" dovrebbe essere 12something ... – momo

+0

Un liner: 'CONCAT (IF (SUBSTRING (id, 1, 2) <= '96', '20', '19'), id) ' – biziclop

Problemi correlati