【问题标题】:Arithmetic calculations on two date-columns in MySQLMySQL中两个日期列的算术计算
【发布时间】:2015-03-27 14:27:53
【问题描述】:

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

这些列是:

trans_date 类型为 DATETIME(例如:2006-02-20 00:00:00

birth 类型为 YEAR(ex: 1970

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

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

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

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

【问题讨论】:

  • 您的查询没有按原样工作吗?
  • 看起来应该可以了。你试过运行它吗?
  • 是的。它不起作用。我得到“BIGINT UNSIGNED 值超出范围'(年(myDB.myTable.trans_date)-myDB.myTable.birth)'”

标签: mysql sql database


【解决方案1】:

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 之后)。

【讨论】:

  • 这里奇怪的是实际上没有出生>年(trans_date)的实例。至于准确度,得到年份的年龄(交易年份 - 出生年份)就足够了
  • @Christoffer 这很奇怪。如果 allbirth
【解决方案2】:

在此处使用 YEAR() 会不精确,因为它不会正确匹配部分年份/说明某人的生日已经过去或尚未过去的事实。

您可以将他们的出生日期的全部部分与当前日期进行比较,但这将是低效的,因为 MySQL 必须对每一行进行计算,因此不能使用索引。

最好的方法是计算目标“出生”日期并将列与该日期进行比较,这样您也可以使用列上的索引。

例子:

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

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

【讨论】:

  • 问题是我只有出生年份,没有完整日期。出生日期列的类型为 YEAR,仅包含年份。
  • 对不起,你是对的,这个答案不正确,没有帮助。我也错过了 trans_date 不是当前日期的事实。
  • 不,这很有帮助。给了我更多的尝试,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 2018-03-18
  • 2012-07-11
相关资源
最近更新 更多