2010-10-18 16 views
24

Attualmente sto sviluppando un'applicazione che visualizza i documenti e consente ai membri di cercare questi documenti con una serie di parametri diversi, uno dei quali è l'intervallo di date.Crea data dai campi giorno, mese, anno in MySQL

Il problema che sto avendo è che lo schema del database non è stato sviluppato da me e il creatore del database ha creato una tabella 'data' con i campi per 'giorno', 'mese', 'anno'.

Vorrei sapere come posso selezionare un giorno, un mese, un anno specifico dalla tabella e creare un oggetto data in SQL in modo da poter confrontare le date immesse dall'utente utilizzando BETWEEN.

Di seguito si riporta la struttura della tabella Data:

CREATE TABLE IF NOT EXISTS `date` (
    `deposition_id` varchar(11) NOT NULL default '', 
    `day` int(2) default NULL, 
    `month` int(2) default NULL, 
    `year` int(4) default NULL, 
    PRIMARY KEY (`deposition_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
+8

oh yuk. perché le persone lo fanno nei loro database? :-( – Spudley

+0

In realtà ho finito per alterare la tabella del database per creare un campo datetime e poi concatenare i campi anno, mese, giorno e aggiornare le righe in base a deposition_id. Sembra aver funzionato bene – TGuimond

+0

@Spudley purtroppo questo non è raro ... anche l'API 'crunchbase' restituisce le date in questo modo ... fa schifo ...:-( – Optimus

risposta

27

È possibile utilizzare la funzione STR_TO_DATE().

+5

STR_TO_DATE (CONCAT ('date_year', '-', LPAD (' date_month', 2, '00 '),' - ', LPAD ('date_day', 2, '00')), '% Y -% m-% d ') –

+3

Non è necessario per 'LPAD' le cifre.' STR_TO_DATE' lo fa per te: 'STR_TO_DATE (CONCAT (date_year,' - ', date_month,' - ', date_day),'% Y -% m-% d ') ' – pbarney

+0

Non so perché SO stia modificando la quota singola in un'entità html proprio lì. – pbarney

1

Provare a usare CONCAT() e lo rendono un campo e confrontare.

Non sono sicuro che sia possibile confrontarlo come data dopo la concatenazione.

È possibile confrontare come numero intero.

concatinato anno mese giorno e creare un numero intero come questo 20101017 e confrontare.

Speriamo :)

17

Per creare una stringa di data ordinabile, è necessario unire CONCAT per unire i bit e LPAD per assicurarsi che i campi del mese e del giorno siano di due cifre. Qualcosa di simile a questo:

CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00')) 

Una volta che hai questo, si dovrebbe essere in grado di utilizzare BETWEEN, come essi saranno in un formato ordinabile. Tuttavia, se è ancora necessario convertirli in campi datetime effettivi, è possibile racchiudere l'intero valore in UNIX_TIMESTAMP() per ottenere un valore di timestamp.

Così ci si finisce con qualcosa di simile:

SELECT UNIX_TIMESTAMP(CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00'))) as u_date 
WHERE u_date BETWEEN timestamp_1 and timestamp_2 

Tuttavia, essere consapevoli che questo sarà massicciamente più lento se il campo era solo una semplice timestamp, in primo luogo. E dovresti assolutamente assicurarti di avere un indice sui campi anno, mese e giorno.

33

Quando si hanno valori interi per anno, mese e giorno, è possibile effettuare un DATETIME combinando MAKEDATE() e DATE_ADD(). MAKEDATE() con una costante giornata di 1 vi darà un DATETIME per il primo giorno del dato anno, e poi si può aggiungere ad essa il mese e il giorno con DATE_ADD():

mysql> SELECT MAKEDATE(2013, 1); 
+-------------------+ 
| MAKEDATE(2013, 1) | 
+-------------------+ 
| 2013-01-01  | 
+-------------------+ 

mysql> SELECT DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH); 
+---------------------------------------------------+ 
| DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH) | 
+---------------------------------------------------+ 
| 2013-03-01          | 
+---------------------------------------------------+ 

mysql> SELECT DATE_ADD(DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH), INTERVAL (11)-1 DAY); 
| DATE_ADD(DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH), INTERVAL (11)-1 DAY) | 
+----------------------------------------------------------------------------------+ 
| 2013-03-11                  | 
+----------------------------------------------------------------------------------+ 

Quindi, per rispondere alla Domanda OP:

SELECT * FROM `date` 
WHERE DATE_ADD(DATE_ADD(MAKEDATE(year, 1), INTERVAL (month)-1 MONTH), INTERVAL (day)-1 DAY) 
BETWEEN '2013-01-01' AND '2014-01-01'; 
+5

Sicuramente più elegante della creazione e dell'uso di stringhe – SEoF

+1

buona soluzione - perché MySQL non ha questo nativo? in questo modo è molto più probabile che l'uso abbia luogo con 100 o qualsiasi altro giorno –

Problemi correlati