2010-10-18 33 views
24

Actualmente estoy desarrollando una aplicación que muestra documentos y permite a los miembros buscar estos documentos por una serie de parámetros diferentes, uno de ellos es el rango de fechas.Crear fecha de día, mes, año campos en MySQL

El problema que tengo es que el esquema de la base de datos no fue desarrollado por mí mismo y el creador de la base de datos ha creado una tabla de 'fecha' con campos para 'día', 'mes', 'año'.

Me gustaría saber cómo puedo seleccionar un día, mes, año específico de la tabla y crear un objeto de fecha en SQL para poder comparar las fechas ingresadas por el usuario usando BETWEEN.

A continuación se muestra la estructura de la tabla de fechas:

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. ¿Por qué la gente hace eso en sus bases de datos? :-( – Spudley

+0

De hecho, terminé alterando la tabla de la base de datos para crear un campo de fecha y hora y luego concatené los campos de año, mes y día y actualicé las filas según deposition_id. Parece que funcionó. – TGuimond

+0

@Spudley lamentablemente esto no es raro ... incluso la API 'crunchbase' devuelve las fechas de esta manera ... apesta ...:-( – Optimus

Respuesta

27

Puede utilizar STR_TO_DATE() función.

+5

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

+3

No es necesario 'LPAD' los dígitos.' STR_TO_DATE' hace eso por usted: 'STR_TO_DATE (CONCAT (date_year,' - ', date_month,' - ', date_day),'% Y -% m-% d ') ' – pbarney

+0

No estoy seguro de por qué SO está cambiando la comilla simple en una entidad html allí – pbarney

1

Intente utilizar CONCAT() y lo convierten en un campo y comparar.

No estoy seguro de que pueda compararlo como fecha después de la concatenación.

Puede comparar como número entero.

concatinate año mes y haga un número como este 20101017 y compare.

suerte :)

17

Para construir una cadena de fecha ordenable a partir de eso, necesitará CONCAT para unir los bits y LPAD para asegurarse de que los campos de mes y día tienen dos dígitos de longitud. Algo como esto:

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

Una vez que tenga eso, usted debería ser capaz de utilizar BETWEEN, ya que van a estar en un formato puede ordenar. Sin embargo, si todavía necesita convertirlos a campos de fecha y hora reales, puede envolver todo en UNIX_TIMESTAMP() para obtener un valor de marca de tiempo.

Por lo que iba a terminar con algo como esto:

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 

Sin embargo, tenga en cuenta que esta será masivamente más lento que si el campo era sólo una marca de tiempo simple en el primer lugar. Y definitivamente debe asegurarse de tener un índice en los campos de año, mes y día.

33

Cuando tiene valores enteros para año, mes y día, puede hacer un DATETIME combinando MAKEDATE() y DATE_ADD(). MAKEDATE() con un día constante de 1 le dará una fecha y hora para el primer día del año dado, y luego se puede añadir a la misma el mes y día 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                  | 
+----------------------------------------------------------------------------------+ 

Así que para responder a la Pregunta de 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

Ciertamente más elegante que la creación y el uso de cadenas – SEoF

+1

buena solución: ¿por qué MySQL no tiene este nativo? como este es un uso mucho más probable que el año con 100 o cualquier día –

Cuestiones relacionadas