MySQL - 比较 WHERE 子句中的两个日期
MySQL - Comparing two dates in the WHERE clause
我有一个 table、links
将两个类别(parent 和 child)链接在一起。 table 有五个字段:
- autoinc
- parent_category_name 年 (4) NOT NULL
- parent_category_year varchar(255) 不为空
- child_category_name 年 (4) NOT NULL
- child_category_year varchar(255) NOT NULL
我正在尝试编写一个 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
此查询工作正常,但我需要应用一些业务规则。规则是:
- parent 年份必须与 child 年份相同
或
- parent年必须比child年
小一年
我在查询中添加了一个 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
条件下的一个(或多个)减去值返回负值。
现在,您可以尝试以下几种选择:
- 您可以使用 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
- 或者您可以按原样设置 NO_UNSIGNED_SUBTRACTION
sql_mode
和 运行 查询:
SET sql_mode='NO_UNSIGNED_SUBTRACTION'
- 您还可以考虑将
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
添加到无符号值应该没有问题。
我有一个 table、links
将两个类别(parent 和 child)链接在一起。 table 有五个字段:
- autoinc
- parent_category_name 年 (4) NOT NULL
- parent_category_year varchar(255) 不为空
- child_category_name 年 (4) NOT NULL
- child_category_year varchar(255) NOT NULL
我正在尝试编写一个 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
此查询工作正常,但我需要应用一些业务规则。规则是:
- parent 年份必须与 child 年份相同
或
- parent年必须比child年 小一年
我在查询中添加了一个 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
条件下的一个(或多个)减去值返回负值。
现在,您可以尝试以下几种选择:
- 您可以使用 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
- 或者您可以按原样设置 NO_UNSIGNED_SUBTRACTION
sql_mode
和 运行 查询:
SET sql_mode='NO_UNSIGNED_SUBTRACTION'
- 您还可以考虑将
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
添加到无符号值应该没有问题。