【问题标题】:MySQL 5.6 Selecting months and daysMySQL 5.6 选择月份和日期
【发布时间】:2016-09-17 10:30:12
【问题描述】:

我很难理解 MySQL 的日期函数。

例如,我想获取本月和上月的所有记录。

据我了解,我应该使用 MONTH(NOW()) 返回当前月份的整数和上个月的 MONTH(NOW())-1。除非要求在一月份的日期,否则这显然不会起作用,因为它是在函数的结果上执行的,而不是环绕并转到前一年的 12 月。

我将如何编写一个在 1 月份也可以使用的通用函数?由于月份的长度不同,因此无法从 NOW() 中减去以毫秒为单位的月份。

例如,这个查询除了 1 月外都能正常工作:

SELECT
          SUM(CASE WHEN MONTH(table_date) = MONTH(NOW())-1 THEN 1 ELSE 0 END) AS LAST_MONTH,
          SUM(CASE WHEN MONTH(table_date) = MONTH(NOW()) THEN 1 ELSE 0 END) AS THIS_MONTH
          FROM table
          WHERE table_date BETWEEN Date_add(NOW(), interval - 1 month) AND  NOW()

DAY() 函数也会出现类似的问题,因为月份的长度不同,而且每天编写语句似乎效率不高。

有什么更有效的方法可以为感兴趣的月份的每一天选择记录,而不管该特定日期是否实际有记录?

【问题讨论】:

    标签: mysql sql date mysql-5.6


    【解决方案1】:

    您很容易从所有年份中提取记录,而不仅仅是存储在 table_date 中的当前记录。要摆脱它,您还需要对年份进行操作,这可以通过始终计算正确的日期格式YYYY-MM-DD 来完成,以免丢失精度。

    这里有一些用于构建最终查询的计算。

    每月的第一天:

    SELECT DATE_FORMAT(table_date, '%Y-%m-01') FROM table
    

    上个月的第一天:

    SELECT DATE_FORMAT(DATE_SUB(table_date, INTERVAL 1 MONTH), '%Y-%m-01') FROM table
    

    一个月的最后一天:

    SELECT LAST_DAY(table_date) FROM table
    

    上个月的最后一天:

    SELECT LAST_DAY(DATE_SUB(table_date, INTERVAL 1 MONTH)) FROM table
    

    您的最终查询:

    SELECT
      SUM(CASE WHEN table_date BETWEEN DATE_FORMAT(table_date, '%Y-%m-01') AND LAST_DAY(table_date) THEN 1 END) AS this_month,
      SUM(CASE WHEN table_date BETWEEN DATE_FORMAT(DATE_SUB(table_date, INTERVAL 1 MONTH), '%Y-%m-01') AND LAST_DAY(DATE_SUB(table_date, INTERVAL 1 MONTH)) THEN 1 END) AS last_month
    FROM table
    WHERE 
      table_date BETWEEN 
       DATE_FORMAT(DATE_SUB(table_date, INTERVAL 1 MONTH), '%Y-%m-01')
       AND LAST_DAY(table_date)
    

    注意:在 case 表达式中,我省略了 ELSE 0,因为 CASE 中 ELSE 的默认语句为 null 并且 SUM() 忽略 null 值:-)

    【讨论】:

    • 抱歉响应缓慢,我突然切换到了不同的子系统。很好的查询细分,清晰的解释,因此被接受为最佳答案。
    【解决方案2】:

    您的逻辑对于其他年份的日期也不安全。 实现您想要的方法可能是将日期截断到本月的第一天,例如(将NOW替换为2013-01-20

    select table_date, 
    case when date_format(table_date, '%Y-%m-01') 
      = date_format('2013-01-20', '%Y-%m-01') then 1 end AS THIS_MONTH,
    case when date_format(table_date, '%Y-%m-01')
      = date_add(date_format('2013-01-20', '%Y-%m-01'), interval -1 month) then 1 end AS LAST_MONTH
    from x;
    

    看到这个SqlFiddle

    【讨论】:

      【解决方案3】:

      您的逻辑将日期转换为整数,然后从中减去 1。对于像 1 月这样的日期和月份,该值变为 1。如果从中减去 1,它将变为 0,这不是有效的日期或月份。

      一个月试试这个:sum(case when month(table_date) = month(date_sub(curdate(), interval 1 month)) then 1 else 0 end) as last_month

      你可以连续几天使用类似的逻辑

      【讨论】:

        【解决方案4】:

        你可以试试这个吗:

        SELECT table_date, 
        SUM(CASE WHEN (LEFT(table_date, 7) = LEFT(NOW(),7)) THEN 
                1 
            ELSE 0 END) AS THIS_MONTH,
        SUM(CASE WHEN 
            (LEFT(table_date, 7) = LEFT(DATE_SUB(NOW(), INTERVAL 1 MONTH),7)) THEN 
            1 ELSE 0 END) AS LAST_MONTH
        FROM table
        WHERE LEFT(table_date, 7) BETWEEN LEFT(DATE_SUB(NOW(), INTERVAL 1 MONTH),7) 
        AND LEFT(NOW(),7)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多