MySQL - 比较 WHERE 子句中的两个日期

MySQL - Comparing two dates in the WHERE clause

我有一个 table、links 将两个类别(parent 和 child)链接在一起。 table 有五个字段:

我正在尝试编写一个 INSERT SELECT,它同时获取 parent 和 child category_id,并将其插入临时文件 table。

INSERT INTO temp (parent_category_id, child_category_id)
SELECT parent.parent_category_id, child.child_category_id
  FROM links
  JOIN categories AS parent
       ON   parent.name = link.parent_category_name
       AND  parent.year = link.parent_category_year
  JOIN categories AS child
       ON   child.name = link.child_category_name
       AND  child.year = link.child_category_year

此查询工作正常,但我需要应用一些业务规则。规则是:

我在查询中添加了一个 WHERE 子句:

WHERE link.child_category_year = link.parent_category_year
   OR link.child_category_year - link.parent_category_year = 1 

在我的 Perl 代码中执行此 INSERT 语句时,出现以下异常:

DBI Exception: DBD::mysql::db do failed: BIGINT UNSIGNED value is out of range in '(`my_database`.`links`.`child_category_year` - `my_database`.`links`.`parent_category_year`)' [for Statement "

所以,我认为 INSERT 不喜欢我在 WHERE 子句中减去日期。我探索了使用 DATEDIFF 函数,但我不仅仅是在寻找日期的一年差异,而是 parent 比 child.

少一年

如何在没有插入错误的情况下完成此操作?

OR link.child_category_year - link.parent_category_year = 1 可能会产生负的减法结果。当然,负值不能存储为 UNSIGNED。

只需将您的表达式转换为

OR link.child_category_year = link.parent_category_year + 1 

这是我第一次知道有 YEAR 数据类型,在阅读 official documentation 之后我了解到:

MySQL displays YEAR values in YYYY format, with a range of 1901 to 2155, and 0000.

虽然,它没有具体说类型是 UNSIGNED 但文档的最后一行说:

If strict SQL mode is not enabled, MySQL converts invalid YEAR values to 0000. In strict SQL mode, attempting to insert an invalid YEAR value produces an error.

这意味着您收到错误,因为 OR link.child_category_year - link.parent_category_year = 1 条件下的一个(或多个)减去值返回负值。

现在,您可以尝试以下几种选择:

  1. 您可以使用 CAST 函数并将年份数据更改为 SIGNED,例如:
WHERE link.child_category_year = link.parent_category_year
   OR CAST(link.child_category_year AS SIGNED) - CAST(link.parent_category_year AS SIGNED) = 1 
  1. 或者您可以按原样设置 NO_UNSIGNED_SUBTRACTION sql_mode 和 运行 查询:
SET sql_mode='NO_UNSIGNED_SUBTRACTION'
  1. 您还可以考虑将 YEAR 数据类型更改为 INTEGER 和 运行 查询:
ALTER TABLE links 
        MODIFY parent_category_year INT NOT NULL,
        MODIFY child_category_year INT NOT NULL;

完全不清楚为什么将“年”存储为无符号 bigint。对于我对“年”的理解,这太过分了。

无论如何,为什么不将逻辑改写为:

WHERE link.parent_category_year = link.child_category_year
      link.parent_category_year = link.child_category_year + 1 

一般来说,将 1 添加到无符号值应该没有问题。