MySQL日期比较出现意外结果:不同查询方式差异原因咨询
问题根源:MySQL的隐式类型转换规则
你遇到的问题完全是MySQL隐式类型转换在搞鬼,咱们逐个拆解这几个查询的行为,就能彻底搞明白差异在哪:
1. 为什么SET @THIS_YEAR = "2019-01-01 00:00:00"; SELECT * FROM table WHERE date > year(@THIS_YEAR);会返回往年数据?
这里的year(@THIS_YEAR)函数返回的是整数2019,而你的date列实际是datetime类型(你说的date类型应该是笔误,因为格式带时分秒)。当MySQL遇到datetime和整数比较时,它会把datetime值转换成整数——转换规则是直接去掉所有非数字字符,比如:
2018-12-31 23:59:59→201812312359592019-01-01 00:00:00→20190101000000
现在你拿这个超大的转换后整数和2019比,显然20181231235959远大于2019,所以所有往年数据都会被筛选出来,这就是结果不符合预期的原因。
2. 为什么SELECT * FROM table WHERE date > "2019";能得到正确结果?
这里的"2019"是字符串类型,MySQL在比较datetime和字符串时,会尝试把字符串转换成datetime类型。MySQL对日期字符串的容错性很高,"2019"会被自动补全为合法的起始日期2019-01-01 00:00:00,所以这个查询等价于:
SELECT * FROM table WHERE `date` > '2019-01-01 00:00:00';
自然就能筛选出2019年及以后的数据。
3. 为什么SELECT * FROM table WHERE date > 2019;也会返回错误结果?
这个和第一个用变量的情况本质完全一致:2019是整数,MySQL会把date列的所有值都转换成去掉非数字的大整数,比如2018-05-01 10:00:00变成20180501100000,这个数远大于2019,所以所有往年数据都会被包含进来。
正确的写法建议
想要避免这类问题,推荐直接使用日期字符串进行比较,或者保证变量类型和列类型一致:
- 直接用日期字符串匹配(推荐,能用到
date列的索引):SELECT * FROM table WHERE `date` >= '2019-01-01 00:00:00'; - 使用变量时,保持变量为日期类型:
SET @THIS_YEAR = '2019-01-01 00:00:00'; SELECT * FROM table WHERE `date` > @THIS_YEAR; - 如果一定要用
year()函数,写法应该是这样(但注意这种写法无法用到索引,数据量大时性能差):SELECT * FROM table WHERE YEAR(`date`) >= 2019;
内容的提问来源于stack exchange,提问作者user1970122
相关产品推荐
相关产品推荐

