【问题标题】:How to get first day of every corresponding month in mysql?如何在mysql中获取每个相应月份的第一天?
【发布时间】:2011-03-18 22:01:17
【问题描述】:

我想获得当年每个相应月份的第一天。例如,如果用户选择“2010-06-15”,则查询要求从“2010-06-01”开始运行,而不是“2010-06-15”。

请帮助我如何计算所选日期的第一天。目前,我正在尝试使用以下 mysql 选择查询:

Select
  DAYOFMONTH(hrm_attendanceregister.Date) >=
  DAYOFMONTH(
    DATE_SUB('2010-07-17', INTERVAL - DAYOFMONTH('2010-07-17') + 1 DAY
  )
FROM
  hrm_attendanceregister;

谢谢

【问题讨论】:

    标签: mysql date


    【解决方案1】:

    这是你要找的东西吗:

    select CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE);
    

    【讨论】:

    • 这是不必要的开销。您正在将日期转换为字符串,然后再次转换回日期。我的解决方案要好得多。
    • 这比我的回答要好。
    【解决方案2】:

    您可以使用 MySQL 提供的LAST_DAY 函数来检索任意月份的最后一天,这很简单:

    SELECT LAST_DAY('2010-06-15');
    

    将返回:

    2010-06-30
    

    不幸的是,MySQL 没有提供任何FIRST_DAY 函数来检索一个月的第一天(不知道为什么)。但是给定最后一天,您可以添加一天并减去一个月以获得第一天。因此您可以定义一个自定义函数:

    DELIMITER ;;
    CREATE FUNCTION FIRST_DAY(day DATE)
    RETURNS DATE DETERMINISTIC
    BEGIN
      RETURN ADDDATE(LAST_DAY(SUBDATE(day, INTERVAL 1 MONTH)), 1);
    END;;
    DELIMITER ;
    

    这样:

    SELECT FIRST_DAY('2010-06-15');
    

    将返回:

    2010-06-01
    

    【讨论】:

    • 您的FIRST_DAY 解决方案在语义上是间接的,因为您是在上个月的最后一天加上 1 天,而不是简单地减去当前日期的天数。参考我的解决方案。
    【解决方案3】:

    实际上有一个简单的解决方案,因为每月的第一天就是today - (day_of_month_in_today - 1)

    select now() - interval (day(now())-1) day
    

    other methods 相比,后者极其迂回和间接。


    另外,由于我们对时间组件不感兴趣,curdate() 是比now() 更好(更快)的函数。我们还可以利用 subdate() 的 2-arity 重载,因为这比使用 interval 性能更高。所以更好的解决方案是:

    select subdate(curdate(), (day(curdate())-1))
    

    【讨论】:

    • 好答案,我认为这是最优雅和高效的解决方案
    • -1 表示傲慢的语气和 cmets。您是否进行了基准测试以表明您的方法是最有效的?我无法想象任何解决方案在典型数据集上都会明显变慢。
    • 仅供参考 - 如果日期戳包含时间组件,此解决方案将无法正常工作。
    • '请帮助我如何计算所选日期的第一天'...这不能回答 O.P.s 的问题...这仅适用于当月。
    【解决方案4】:

    这是旧的,但这可能对新的人类网络爬虫有帮助 XD

    当月的第一天,您可以使用:

    SELECT LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY;
    

    【讨论】:

    • 效率低下。当实际上只需要一个日期减法时,使用一个日期减法和一个日期加法。参考我的解决方案。
    【解决方案5】:

    您可以使用EXTRACT 获取您想要的日期部分:

    EXTRACT( YEAR_MONTH FROM DATE('2011-09-28') )
    -- 201109
    

    这很适合分组。

    【讨论】:

      【解决方案6】:

      我很惊讶没有人提出类似的建议(我不知道它的性能如何):

      CONCAT_WS('-', YEAR(CURDATE()), MONTH(CURDATE()), '1')
      

      如有必要,可以执行其他日期操作以删除格式

      【讨论】:

        【解决方案7】:

        您可以使用 DATE_FORMAT() 函数来获取任何日期字段的第一天。

        SELECT DATE_FORMAT(CURDATE(),'%Y-%m-01') as FIRST_DAY_CURRENT_MONTH 
        FROM dual;
        

        将 Curdate() 更改为任何其他日期字段,例如:

        SELECT DATE_FORMAT(purchase_date,'%Y-%m-01') AS FIRST_DAY_SALES_MONTH 
        FROM Company.Sales;
        

        然后,使用您自己的问题:

        SELECT *
        FROM
          hrm_attendanceregister
        WHERE
        hrm_attendanceregister.Date) >=
         DATE_FORMAT(CURDATE(),'%Y-%m-01')
        

        您可以将 CURDATE() 更改为任何其他给定日期。

        【讨论】:

          【解决方案8】:

          使用date_format 方法并只检查月份和年份

          select * from table_name where date_format(date_column, "%Y-%m")="2010-06"
          

          【讨论】:

          【解决方案9】:

          一个月第一天的计算方法有很多种,以下是我电脑上的表现(你可以在自己电脑上试试)

          获胜者是LAST_DAY(@D - interval 1 month) + interval 1 day

          set @D=curdate();
          
          select BENCHMARK(100000000, subdate(@D, (day(@D)-1))); -- 33 seconds
          SELECT BENCHMARK(100000000, @D - INTERVAL (day(@D) - 1) DAY); -- 33 seconds
          SELECT BENCHMARK(100000000, cast(DATE_FORMAT(@D, '%Y-%m-01') as date)); -- 29 seconds
          SELECT BENCHMARK(100000000, LAST_DAY(@D - interval 1 month) + interval 1 day); -- 26 seconds
          

          【讨论】:

            【解决方案10】:
            date_add(subdate(curdate(), interval day(?) day), interval 1 day)
            

            改变 ?对应日期

            【讨论】:

            【解决方案11】:

            这对我来说很好。

             date(SUBDATE("Added Time", INTERVAL (day("Added Time") -1) day))
            

            ** 用列名替换“添加时间”

            用例:

            1. 如果您想重置除之外的所有日期字段。

            2. 如果您想将列格式保留为“日期”。 (不是“文本”或“数字”)

            【讨论】:

              【解决方案12】:

              慢(17 秒):

              SELECT BENCHMARK(100000000, current_date - INTERVAL (day(current_date) - 1) DAY); 
              SELECT BENCHMARK(100000000, cast(DATE_FORMAT(current_date, '%Y-%m-01') as date));
              

              如果您不需要日期类型,这会更快: 快速(6 秒):

              SELECT BENCHMARK(100000000, DATE_FORMAT(CURDATE(), '%Y-%m-01'));
              SELECT BENCHMARK(100000000, DATE_FORMAT(current_date, '%Y-%m-01'));
              

              【讨论】:

                【解决方案13】:
                SELECT LAST_DAY(date) as last_date, DATE_FORMAT(date,'%Y-%m-01') AS fisrt_date FROM table_name
                

                date=您的列名

                【讨论】:

                  【解决方案14】:

                  使用last_day()然后加/减一个月和一天的解决方案不可互换。

                  例子:

                  date_sub(date_add(last_day(curdate()), interval 1 day), interval 3 month) 
                  

                  始终适用于您想要返回的任何提供的月数

                  date_add(date_sub(last_day(now()), interval 3 month), interval 1 day)
                  

                  在某些情况下会失败,例如,如果您当前的月份有 30 天,而您要减去(然后加上一天)的月份有 31。

                  【讨论】:

                    【解决方案15】:
                    select big.* from
                    (select @date := '2010-06-15')var
                    straight_join 
                    (select * from your_table where date_column >= concat(year(@date),'-',month(@date),'-01'))big;
                    

                    这不会创建全表扫描。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2018-01-11
                      • 1970-01-01
                      • 2022-01-22
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-08-07
                      相关资源
                      最近更新 更多