mysql определение будущих дат на основе записей текущей даты - PullRequest
0 голосов
/ 30 января 2020

Я много исследовал это, но не смог найти ничего похожего на мою проблему, поэтому я публикую сценарий для помощи и руководства по поиску метода - просто укажите мне правильное направление, если это возможно. В отличие от некоторых комментариев ниже, я не совсем знаю, как обеспечить минимальный воспроизводимый запрос, тем более что я не знаю, возможен ли он вообще.

У меня есть таблица mysql, которая содержит записи о событиях. Каждая запись определяет, когда событие должно начаться (startDate) - пример: 4 сентября 2019 (среда). Событие должно повторяться каждую среду после этого, но есть только ОДНА основная запись события. eventFreq указывает, как часто событие должно происходить.

eventFreq = 1 ; // every x day of week (every Wednesday)
eventFreq = 2 ; // every other x day of week (every other Monday)
eventFreq = 3 ; // every 3rd X day of month (every 3rd Tuesday)

Можно ли написать запрос mysql, который на основе основной записи startDate и eventFreq даст мне все случаи среды в следующем месяце (IE: все среды в марте 2020 года)? Или запрос, который даст мне СЛЕДУЮЩУЮ среду в зависимости от текущей текущей даты. Эти запросы должны были бы выяснить, что startDate является средой для начала, чтобы определить будущие.

Если он определит будущую среду в марте 2020 года, он вернет основную запись события плюс дополнительное поле для указания c будущей среды.

Основная запись события: ID, имя-события, eventDescription, startDate, eventFreq, blah1, blah2, blah3

Если среда марта была найдено, что он вернет всю запись с добавленным столбцом nextDate как одну из сред в марте. таким образом, он вернул бы мне те же четыре записи с добавленным столбцом nextDate.

Грубо:

   IF DATE == Wednesday, then Date as nextDate  
OR IF Wednesday BETWEEN FirstDayOfMonth AND LastDayOfMonth  
OR IF Wednesday, then Next Wednesday after today

Возвращает одну и ту же основную запись X раз с добавленным столбцом nextDate:

ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 4 2020
ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 11 2020 
ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 18 2020
ID,eventName,eventDescription,startDate,eventFreq,blah1,blah2,blah3,nextDate // March 25 2020

В настоящее время я извлекаю все события и использую PHP для обработки всех событий startDate и eventFreq (каждую среду) для определения будущих сред. Код обширный и сложный для всех сценариев ios - поэтому я надеялся, что хороший запрос mysql просто вернет правильные будущие даты, а затем все, что мне нужно сделать, это обработать результаты.

Можно ли этого достичь?

1 Ответ

1 голос
/ 31 января 2020

Я думаю, вы пытаетесь положить слишком много вещей в одну корзину. Вы должны разделить их.

  1. Вы можете использовать функции вычисления даты и времени для определения диапазона дат, который вас интересует

  2. Затем вы можете использовать один из способов создать список дат в пределах этого диапазона дат

  3. При желании вы можете отфильтровать даты по некоторым общим критериям (например, исключая воскресенья или публичные c праздники, если обязательно)

  4. Finnaly, вы можете проверить каждую дату в списке, если она соответствует вашим критериям eventFreq. Это может быть реализовано как функция, что-то вроде этого:

CREATE FUNCTION `SP_IsEventFreqMatched`(
    `aDateRef` DATE,
    `aEventFreq` TINYINT UNSIGNED,
    `aDate` DATE
)
RETURNS TINYINT(1) UNSIGNED
DETERMINISTIC
BEGIN
    SET @r = DAYOFWEEK(aDate) = DAYOFWEEK(aDateRef);
    IF @r = 1 THEN
        CASE aEventFreq
            WHEN 1 THEN
                BEGIN
                    -- every x day of week (every Wednesday)
                    -- weekdays already matched. do nothing
                END;

            WHEN 2 THEN
                BEGIN
                    -- every other x day of week (every other Monday)
                    SET @r = (ABS(DATEDIFF(aDate, aDateRef)) / 7) MOD 2 = 0;
                END;

            WHEN 3 THEN
                BEGIN
                    -- every 3rd X day of month (every 3rd Tuesday)
                    SET @r = (ABS(DATEDIFF(aDate, aDateRef)) / 7) MOD 3 = 0;
                END;

            -- You can add logic other eventFreq types

            ELSE
                BEGIN
                    -- todo@ raise an error? 
                    SET @r = 0; 
                END;
        END CASE;
    END IF;

    RETURN @r;
END

Итак, в конце ваш запрос будет выглядеть примерно так (я использую мою технику для генерации дат в диапазон, вы можете найти его по предоставленной ссылке):

SET @from = '2020-02-15';
SET @to   = '2020-03-15';

SELECT
      m.ID
    , m.startDate
    , DAYOFWEEK(m.startDate) - 1 AS weekday
    , m.eventFreq
    , d.d AS nextDate
FROM
      `global`.dates AS d
    , `Master` AS m
WHERE
        d.d BETWEEN @from AND @to
    AND SP_IsEventFreqMatched(m.startDate, m.eventFreq, d.d)
ORDER BY
      m.eventFreq
    , d.d
;

=>

ID  startDate   weekday eventFreq   nextDate
1   2020-01-01  3   1   2020-02-19
1   2020-01-01  3   1   2020-02-26
1   2020-01-01  3   1   2020-03-04
1   2020-01-01  3   1   2020-03-11
2   2020-01-02  4   2   2020-02-27
2   2020-01-02  4   2   2020-03-12
3   2020-01-03  5   3   2020-03-06

Примечание 1. Я использовал переменные сеанса, чтобы указать диапазон дат для простоты. В реальной жизни вам, вероятно, следует рассчитать его на основе ваших критериев поиска или текущей даты.

Примечание 2: Я не понимаю, как бы вы хотели рассчитывать «все остальные». С начала месяца даты или из записи startDate. Я реализовал более поздний в SP. Если вам нужен другой, вам нужно настроить функцию.

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