我该如何进行日期计算?

时间:2011-11-20 20:17:47

标签: mysql sql

我的表格中有一列名为expiry_date。我使用以下查询返回此日期,加上6个月:

SELECT DATE_ADD(expiry_date, INTERVAL 6 MONTH) AS expiry_date;

我想修改上述内容,以便如果expiry_date加上过去6个月(CURRENT_DATE之前),则根据需要再添加6个月,直到日期为止在将来。

我怎样才能使用MySQL?

3 个答案:

答案 0 :(得分:2)

第一种方法:

SELECT 
   case when expiry_date > SYSDATE() then
       DATE_ADD(   expiry_date  , INTERVAL 6 MONTH) 
   else
       DATE_ADD(
          DATE_SUB( 
             SYSDATE(),   
             INTERVAL 
             ( DATEDIFF( SYSDATE(), expiry_date )  % ( 6 * 30) )  
             MONTH
          )
          , 
          INTERVAL 6 MONTH) 
   end
   AS expiry_date
FROM ...

未经测试。

答案 1 :(得分:1)

我用以下数据对此进行了测试:

Table: `test`
uid      expiry_date
1        2011-11-03
2        2011-01-20

代码:

SELECT 
    `uid`,
    `expiry_date`,
    PERIOD_DIFF(
        date_format(DATE_ADD(CURDATE(),INTERVAL 1 DAY),'%Y%m'),
        date_format(`expiry_date`,'%Y%m')
    ) as `dif`, /* Straight Month Difference */
    CEIL(PERIOD_DIFF(
        date_format(DATE_ADD(CURDATE(),INTERVAL 1 DAY),'%Y%m'),
        date_format(`expiry_date`,'%Y%m')
    )/6) AS `dif2`, /* How many blocks of 6 months, rounded up */
    (
        IF(
            ( /* If 1 block is > today, add the 6 months and finish */
            DATE_ADD(
                CURDATE(),
                INTERVAL 1 DAY
            ) < DATE_ADD(
                `tOuter`.`expiry_date`,
                INTERVAL 6 MONTH
            )
        ), /* this is with just 6 months added */
        DATE_ADD(
            `tOuter`.`expiry_date`,
                INTERVAL 6 MONTH
            ), /* this works out how many blocks of 6 months to add */
            DATE_ADD(
                `tOuter`.`expiry_date`,
            INTERVAL (
                6 * CEIL( /* round up number of months */
                    PERIOD_DIFF( /* get number of months */
                        date_format(
                            DATE_ADD(
                                CURDATE(),
                                INTERVAL 1 DAY
                            ),
                            '%Y%m'
                        ),
                        date_format(
                            `expiry_date`,
                            '%Y%m'
                        )
                    )/6 /* divide months by 6 to match question */
                )
            ) MONTH /* add the dynamically calculated interval */
        )
    )
) AS `expiry_date_calculated` FROM `test` AS `tOuter`

结果是:

uid     expiry_date      dif         dif2       expired_date_calculated
1       2011-11-03       0           0          2012-05-03
2       3011-01-20       10          2          2012-01-20

这是此输入的所需输出吗?

性能提示:这在性能上非常糟糕,我邀请其他人建议更有效的例程。这可能更好地编写为存储过程,如果将CURDATE()的日期作为字符串传递,则肯定会更好。

示例:使用2个字段,需要0.04秒才能生成上述所需的结果。

编辑:较小的版本:

SELECT 
 `id`, `expiry_date`,
 (IF((DATE_ADD(CURDATE(),INTERVAL 1 DAY) < DATE_ADD(`expiry_date`,INTERVAL 6 MONTH)),
   DATE_ADD(`expiry_date`,INTERVAL 6 MONTH),
   DATE_ADD(`expiry_date`,
    INTERVAL (6 * CEIL(PERIOD_DIFF(
        date_format(DATE_ADD(CURDATE(),INTERVAL 1 DAY),'%Y%m'),
        date_format(`expiry_date`,'%Y%m')
    )/6)) MONTH
   )
 )
) AS `expiry_date_calculated`

答案 2 :(得分:0)

您应该在expiry_date中添加 X年6个月 X年12个月。 X是他们年份部分off now()和expiry_date之间的差异。

select if(dayofyear(expiry_date)>=dayofyear(now()), 
 date_add(test, interval concat(year(now())-year(expiry_date), '-6') year_month), 
 date_add(test, interval concat(year(now())-year(expiry_date), '-12') year_month)) 
as expiry_date from <table>;

一个例子。 expiry_date是2009-10-01

dayofyear(expiry_date)是274

dayofyear(now())是325

所以第一个条件是假的。 concat(year(now())-year(expiry_date), '-12'给出了2011-2009 = 2年12个月(字符串为&#39; 2-12&#39;),用于date_add('2009-10-01', interval '2-12' year_month,即2011-10-01 + 6个月= 2012-05-01。