从MySQL中的日,月,年字段创建日期

TGu*_*ond 39 mysql sql database datetime

我目前正在开发一个显示文档的应用程序,并允许成员通过许多不同的参数搜索这些文档,其中一个参数是日期范围.

我遇到的问题是数据库模式不是由我自己开发的,数据库的创建者创建了一个'日期'表,其中包含'day','month','year'字段.

我想知道如何从表中选择特定的日,月,年并在SQL中创建日期对象,以便我可以使用BETWEEN比较用户输入的日期.

以下是日期表的结构:

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;
Run Code Online (Sandbox Code Playgroud)

小智 47

如果您有年,月和日的整数值,则可以通过组合MAKEDATE()和DATE_ADD()来创建DATETIME.MAKEDATE()的常数为1天将为您提供给定年份第一天的DATETIME,然后您可以使用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                                                                       |
+----------------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

所以回答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';
Run Code Online (Sandbox Code Playgroud)

  • 当然比创建和使用字符串更优雅. (6认同)
  • 很好的解决方案 - 为什么MySQL没有这个原生?似乎这比100年或任何日子的年份更有可能使用 (2认同)

Sac*_*hag 37

您可以使用STR_TO_DATE()函数.

  • STR_TO_DATE(CONCAT(`date_year`,'-',LPAD(`date_month`,2,'00'),'-',LPAD(`date_day`,2,'00')), '%Y-%m- %d') (11认同)
  • 没有必要"LPAD"数字.`STR_TO_DATE`为你做的:`STR_TO_DATE(CONCAT(date_year,' - ',date_month,' - ',date_day),'%Y-%m-%d')` (6认同)
  • @pbarney我想补充一下,STR_TO_DATE('1-1-1,'%Y-%m-%d')`的计算结果要到2001年1月的第一天,至少是在测试它的MySQL DB上。如果您不喜欢这种行为,则必须对年份组件进行“ LPAD”处理,以便拥有“ STR_TO_DATE('0001-1-1','%Y-%m-%d')”,该函数将返回第一个1月1日。我不知道是否有任何区域性配置或可以更改的任何内容,以避免不得不在当年使用“ LPAD”,但是我没有找到它。 (2认同)

Spu*_*ley 17

要从中构建可排序的日期字符串,您需要CONCAT将这些位加在一起并LPAD确保月和日字段长度为两位数.像这样的东西:

CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00'))
Run Code Online (Sandbox Code Playgroud)

一旦你有了,你应该能够使用BETWEEN,因为它们将是一种可排序的格式.但是,如果您仍然需要将它们转换为实际的日期时间字段,则可以将整个内容包装起来UNIX_TIMESTAMP()以获取时间戳值.

所以你最终得到这样的东西:

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
Run Code Online (Sandbox Code Playgroud)

但是,要知道,这将是大量比如果该字段只是摆在首位简单的时间戳慢.你一定要确保你有年,月,日字段的索引.


Gan*_*net 6

最简单的方法是:

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

LPAD并非必需,如@pbarney先前指出的那样。如果要与另一个日期对象进行比较,则不一定要用DATE包装它,因为MySQL会自动将其转换:

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