我有一个日期表,其中有一列date
(PK)。 CREATE
脚本在这里:
CREATE TABLE date_table (
date DATE
,year INT(4)
,month INT(2)
,day INT(2)
,month_pad VARCHAR(2)
,day_pad VARCHAR(2)
,month_name VARCHAR(10)
,year_month_index INT(6)
,year_month_hypname VARCHAR(7)
,year_month_name VARCHAR(15)
,week_day_index INT(1)
,day_name VARCHAR(9)
,week INT(2)
,week_interval VARCHAR(13)
,weekend_fl INT(1)
,quarter_num INT(1)
,quarter_num_pad VARCHAR(2)
,quarter_name VARCHAR(2)
,year_quarter_index INT(6)
,year_quarter_name VARCHAR(7)
,PRIMARY KEY (date)
);
现在,我希望使用动态值从此表中选择行,例如LAST_DAY()
或DATE_SUB(DATE_FORMAT(SYSDATE(),'%Y-01-01'), INTERVAL X YEAR)
等。
当我的一个查询失败并且在30秒内没有执行时,我知道有些东西是可疑的,看起来原因是没有使用主键列上的索引。这是我的结果(抱歉使用图像而不是复制查询,但我认为它的简洁性足够用于此目的,并且查询简短/简单):
首先,BETWEEN
与使用>=
和<=
的工作方式不同,这很奇怪。其次,看起来索引仅用于常量值。如果仔细观察,可以看到右侧(使用>=
和<=
),它显示~9K行,这是表中行的一半(表中有关于~18k行,日期从2000-01-01
到“2050-12-31”。
答案 0 :(得分:1)
SYSDATE()返回执行的时间。这与NOW()的行为不同,后者返回一个表示语句开始执行的时间的常量时间。 (在存储的函数或触发器中,NOW()返回函数或触发语句开始执行的时间。)
- https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_sysdate
也就是说,优化器不会将此视为“常量”。否则,优化器会急切地评估任何“常量表达式”,然后尝试利用知道值。
另请参阅sysdate_is_now
选项。
结论:不要将SYSDATE()
用于正常的日期时间使用;使用NOW()
或CURDATE()
。
答案 1 :(得分:0)
如果我使用CURRENT_DATE()
(或NOW()
)代替SYSDATE()
,我们就可以了。这两个查询都是:
SELECT *
FROM date_table t
WHERE 1 = 1
AND t.ddate >= LAST_DAY(CURRENT_DATE()) AND t.ddate <= LAST_DAY(CURRENT_DATE());
SELECT *
FROM date_table t
WHERE 1 = 1
AND t.ddate >= LAST_DAY(NOW()) AND t.ddate <= LAST_DAY(NOW());
给出相同的结果,即:
我会接受我的答案作为解决方案,但我仍然在寻找解释。我认为可能必须做SYSDATE()
而不是DATE
,但NOW()
也不是DATE
......
编辑:忘记添加,BETWEEN
也正常工作。