web-dev-qa-db-fra.com

Créer une date à partir des champs jour, mois et année dans MySQL

Je développe actuellement une application qui affiche des documents et permet aux membres de rechercher ces documents par un certain nombre de paramètres différents, l'un d'eux étant la plage de dates.

Le problème que j'ai est que le schéma de la base de données n'a pas été développé par moi-même et que le créateur de la base de données a créé une table "date" avec des champs pour "jour", "mois", "année".

Je voudrais savoir comment je peux sélectionner un jour, un mois, une année spécifique dans le tableau et créer un objet date dans SQL afin de pouvoir comparer les dates entrées par l'utilisateur à l'aide de BETWEEN.

Voici la structure du tableau des dates:

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;
37
TGuimond

Vous pouvez utiliser la fonction STR_TO_DATE () .

35
Sachin Shanbhag

Lorsque vous avez des valeurs entières pour l'année, le mois et le jour, vous pouvez créer une DATETIME en combinant MAKEDATE () et DATE_ADD (). MAKEDATE () avec un jour constant de 1 vous donnera une DATETIME pour le premier jour de l'année donnée, puis vous pourrez y ajouter le mois et le jour avec 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                                                                       |
+----------------------------------------------------------------------------------+

Donc, pour répondre à la question du PO:

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';
45
Joe Holt

Pour construire une chaîne de date triable à partir de cela, vous aurez besoin de CONCAT pour joindre les bits ensemble et LPAD pour vous assurer que les champs mois et jour comportent deux chiffres. Quelque chose comme ça:

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

Une fois que vous avez cela, vous devriez pouvoir utiliser BETWEEN, car ils seront dans un format triable. Cependant, si vous devez encore les convertir en champs datetime réels, vous pouvez encapsuler le tout dans UNIX_TIMESTAMP() pour obtenir une valeur d'horodatage.

Vous vous retrouveriez donc avec quelque chose comme ceci:

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

Cependant, sachez que cela sera massivement plus lent que si le champ n'était qu'un simple horodatage en premier lieu. Et vous devez absolument vous assurer d'avoir un index sur les champs année, mois et jour.

17
Spudley

La façon la plus simple de le faire est:

DATE(CONCAT_WS('-', year, month, day))

LPAD n'est pas nécessaire comme l'a souligné @pbarney plus tôt. Si vous comparez avec un autre objet date, il n'est pas strictement nécessaire de l'envelopper avec DATE car MySQL le castera automatiquement:

some_date_field > CONCAT_WS('-', year, month, day)

4
Gannet

Essayez d'utiliser CONCAT () et faites-en un seul champ et comparez.

Je ne suis pas sûr que vous puissiez le comparer comme date après la concaténation.

Vous pouvez comparer comme entier.

concatinate year month day et faites un entier comme celui-ci 20101017 et comparez.

Si tout va bien :)

1
zod