Как мне сделать этот расчет даты? - PullRequest
1 голос
/ 21 ноября 2011

В моей таблице есть столбец с именем expiry_date. Я использую следующий запрос для возврата этой даты плюс 6 месяцев:

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

Я бы хотел изменить вышеприведенное, чтобы если expiry_date плюс 6 месяцев было в прошлом (до CURRENT_DATE), дополнительные 6 месяцев добавляются столько раз, сколько необходимо, до даты в будущем.

Как я могу сделать это, используя MySQL?

Ответы [ 3 ]

2 голосов
/ 21 ноября 2011

Первый подход:

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 голос
/ 21 ноября 2011

Я проверил это со следующими данными:

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`
0 голосов
/ 21 ноября 2011

Вы должны добавить либо X лет и 6 месяцев или X лет и 12 месяцев к expiry_date.X - это разница между годовой частью 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>;

Один пример.дата истечения срока действия - 2009-10-01

dayofyear (expiry_date) - 274

dayofyear (now ()) - 325

, поэтому первое условие ложно.concat(year(now())-year(expiry_date), '-12' дает 2011-2009 = 2 года и 12 месяцев (строка «2-12»), и это используется в date_add('2009-10-01', interval '2-12' year_month, что составляет 2011-10-01 + 6 месяцев = 2012-05-01.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...