MySQL中两个日期列的算术计算

时间:2015-03-27 14:27:54

标签: mysql sql database

我有一个大表(> 30M行),其中包含某种交易的信息。有一列有交易的完整日期,有一列有用户的出生年份。

列是:

DATETIME类型的

trans_date例如:2006-02-20 00:00:00

YEAR类型的

birth ex:1970

我想要的是能够在where子句中计算交易中人的年龄。例如,2006年 - 1970年= 36.因此,1970年出生的人在交易当年是36岁。

这就是我想要做的事情(伪代码):

SELECT name FROM table WHERE (YEAR(trans_date) - birth) = '36'

这样我就可以获得交易当年该人36岁的所有记录。这可能吗?

2 个答案:

答案 0 :(得分:2)

当您处理无符号类型并获得负值时,birth > year(trans_date)会发生错误。

您可以通过强制签名结果来解决此问题(假设birth是无符号值):

WHERE (YEAR(trans_date) - CAST(birth AS SIGNED)) = 36

此外,不要对文字编号使用引号 - 计算返回一个数字,您应该将其与数字进行比较,而不是字符串(将隐式转换为数字)。

MySQL手册指出

  

默认情况下,整数操作数之间的减法会产生UNSIGNED   结果,如果任何操作数是UNSIGNED

可以通过更改设置来控制:SET sql_mode = 'NO_UNSIGNED_SUBTRACTION

有关详细信息,请参阅this part of the documentation

另请注意,years的确定并不准确,因为您缺乏实际确定年龄所需的精确度(因为您将日期与年份进行比较,用户的实际出生日期可能是在trans_date之前或之后)。

答案 1 :(得分:1)

在这里使用YEAR()将是不精确的,因为它不能正确匹配部分年份/帐户,因为某人生日已经或尚未过去。

你可以对他们出生日期的整个部分与当前日期进行计算,但是由于MySQL必须对每一行进行计算而不能使用索引,因此这将是低效的。

最佳方法是计算目标“出生日期”并将列与之比较,以便您也可以在列上使用索引。

示例:

WHERE
 trans_date
 BETWEEN
   DATE_SUB(CUR_DATE(), INTERVAL 36 YEAR)
   AND
   DATE_SUB(CUR_DATE(), INTERVAL 37 YEAR)

测试边缘情况(即生日之前,之日或之后1天的交易日期),以确保您正确匹配范围而不是关闭范围。