在DATE_FORMATE()或MONTH(),YEAR()中哪一个更好

时间:2016-04-15 10:00:19

标签: mysql datetime query-optimization

我必须按月收到记录/计数。 没有办法---

1

SELECT COUNT(1)AS approved FROM lu_registration 
WHERE MONTH(approved_date)=MONTH(NOW()) AND YEAR(approved_date)=YEAR(NOW());

2

SELECT COUNT(1)AS approved FROM lu_registration 
WHERE DATE_FORMATE(approved_date, '%Y-%m')=DATE_FORMATE(NOW(), '%Y-%m');

3

SELECT COUNT(CASE WHEN MONTH(approved_date)=MONTH(NOW()) 
AND YEAR(approved_date)=YEAR(NOW()) THEN 1 END)AS approved FROM lu_registration;

4

SELECT COUNT(CASE WHEN DATE_FORMATE(approved_date, '%Y-%m')=DATE_FORMATE(NOW(), '%Y-%m')
 THEN 1 END)AS approved FROM lu_registration;

哪一个最好。

实际Senerio: 有一个月过滤器,我们选择月份,并获得04-2016。这样我们就可以使用date_format(%m-%y)或month = 04&年= 2016年匹配获取记录。但哪一个是表现明智更好

要优化的实际查询是:

SELECT COUNT(CASE WHEN status='A' AND MONTH(approved_date)=04
AND YEAR(approved_date)=2016 THEN 1 END)AS approved, COUNT(CASE WHEN status='D' AND MONTH(reject_date)=04 
AND YEAR(reject_date)=2016 THEN 1 END)AS rejected FROM lu_registration;

这是approved_date& reject_date两个不同的列或已批准的用户也被拒绝

2 个答案:

答案 0 :(得分:3)

您正在尝试计算日期范围内的记录。相对而言,您建议的查询都不是有效的。没有人可以利用approved_date列上的MySQL索引。它们都不是sargeable.这会损害性能,尤其是当您的应用程序添加日期可追溯到几年的记录时。

相反,您需要查询表单

 SELECT COUNT(*) AS approved
   FROM table
  WHERE approved_date >= <<<00:00 on first date>>>
    AND approved_date <  <<<00:00 on day after last date>>>

这可以对approved_date列上的索引执行index scan

因此,现在需要的技巧是从<<<00:00 on first date>>获取<<<00:00 on day after last date>>>NOW()的正确值。这是你做的。

  1. LAST_DAY(NOW())在本月的最后一天给00:00。
  2. LAST_DAY(NOW()) + INTERVAL 1 DAY在下个月的第一天00:00。
  3. LAST_DAY(NOW()) + INTERVAL 1 DAY - INTERVAL 1 MONTH在本月的第一天给00:00。
  4. 因此,您的查询变为

     SELECT COUNT(*) AS approved
       FROM lu_registration
      WHERE approved_date >= LAST_DAY(NOW()) + INTERVAL 1 DAY
        AND approved_date <  LAST_DAY(NOW()) + INTERVAL 1 DAY - INTERVAL 1 MONTH
    

    它选择了正确的日期范围,而且运行速度很快。

    (注意我使用COUNT(*)代替了COUNT(1)。这是因为COUNT(*)是计算记录的常用方法。有时RDMS软件中的查询计划模块会对其进行优化。)

答案 1 :(得分:1)

我认为第一个更好 -

SELECT COUNT(1)AS approved FROM lu_registration 
WHERE MONTH(approved_date)=MONTH(NOW()) AND YEAR(approved_date)=YEAR(NOW());