Mysql 日历定期/重复事件->;查找日期范围内的事件

Mysql 日历定期/重复事件->;查找日期范围内的事件,mysql,sql,date,calendar,Mysql,Sql,Date,Calendar,因此,我试图在中提供的模式和查询的基础上进行构建 上面的主要限制是查询只返回特定日期的事件。我需要查询任意日期范围(范围内的每个日期都不能单独查询) 我的模式: 该日期将在2016年每个月的第四个星期四重复 `date_start` : "2016-01-01" `date_end` : "2016-12-31" `time_start` : NULL, `time_end` : NULL, `repeat_interval` : NULL `repeat_year` : NULL `repe

因此,我试图在中提供的模式和查询的基础上进行构建

上面的主要限制是查询只返回特定日期的事件。我需要查询任意日期范围(范围内的每个日期都不能单独查询)

我的模式: 该日期将在2016年每个月的第四个星期四重复

`date_start` : "2016-01-01"
`date_end` : "2016-12-31"
`time_start` : NULL,
`time_end` : NULL,
`repeat_interval` : NULL
`repeat_year` : NULL
`repeat_month` : NULL
`repeat_day` : NULL
`repeat_nth_day` : 4
`repeat_weekday` : 5 
和一个查询,以获取在单个日期发生的事件: 每2月1日重复一次
但是,它将在2016-02-15-2016-03-15范围内返回,因为该范围包括2月1日(3月1日)。。。但不包括2月1日:(

我想出了一个解决方案,涉及两件我没有太多经验的事情:临时表和循环。我迭代日期范围,并将每个日期结果插入到临时表中

REPEAT
    # events_filter_date inserts into the temporary table
    CALL events_filter_date(_date_cur);
    SET _date_cur = DATE_ADD(_date_cur, INTERVAL 1 DAY);
UNTIL _date_cur > _date_end
END REPEAT;

SELECT *
FROM `events_temp`;

我提出了一个解决方案,涉及两件我没有太多经验的事情:临时表和循环

REPEAT
    # events_filter_date inserts into the temporary table
    CALL events_filter_date(_date_cur);
    SET _date_cur = DATE_ADD(_date_cur, INTERVAL 1 DAY);
UNTIL _date_cur > _date_end
END REPEAT;

SELECT *
FROM `events_temp`;
CREATE DEFINER=`root`@`localhost` PROCEDURE `_events_filter_get_range`(_date_start DATE, _date_end DATE)
BEGIN

    DECLARE _dom_start INT DEFAULT DAYOFMONTH(_date_start);
    DECLARE _dom_end INT DEFAULT DAYOFMONTH(_date_end);
    DECLARE _month_start INT DEFAULT MONTH(_date_start);
    DECLARE _month_end INT DEFAULT MONTH(_date_end);
    DECLARE _year_start INT DEFAULT YEAR(_date_start);
    DECLARE _year_end INT DEFAULT YEAR(_date_end);
    DECLARE _day_diff INT DEFAULT DATEDIFF(_date_end, _date_start);
    DECLARE _month_diff INT DEFAULT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM _date_end), EXTRACT(YEAR_MONTH FROM _date_start));
    DECLARE _year_diff INT DEFAULT _year_end - _year_start;
    #DECLARE _nth_day INT DEFAULT 1 + floor((DAYOFMONTH(_date) - 1) / 7);
    #DECLARE _weekday INT DEFAULT DAYOFWEEK(_date);

    SELECT
        e.*,
        ed.`date_start`,
        ed.`date_end`,
        ed.`time_start`,
        ed.`time_end`
    FROM `events` e
    JOIN `events_dates` ed ON ed.`event_id` = e.`event_id`
    WHERE
        (
            (`date_start` <= _date_end) AND
            (`date_end` >= _date_start) AND
            (ABS(DATEDIFF(_date_end, `date_start`)) % `repeat_interval` <= _day_diff)
        ) OR
        (
            (`date_start` <= _date_end) AND
            (`date_end` >= _date_start) AND
            (`repeat_year` IS NULL OR
                `repeat_year` BETWEEN _year_start AND _year_end) AND
            (`repeat_month` IS NULL OR
                (_month_diff >= 11) OR
                (_year_diff = 0 AND `repeat_month` BETWEEN _month_start AND _month_end) OR
                # Dec 2015 - Jan 2015
                (_year_diff = 1 AND (`repeat_month` <= _month_end OR `repeat_month` >= _month_start))
            ) AND
            (`repeat_day` IS NULL OR
                (_month_diff > 1) OR
                # Jan 25 - Feb 26
                (_month_diff = 1 AND _dom_start < _dom_end) OR
                # Jan 25 - Feb 5
                (_month_diff = 1 AND _dom_start > _dom_end AND (`repeat_day` <= _dom_end OR `repeat_day` >= _dom_start)) OR
                # Jan 25 - Jan 26
                (_month_diff = 0 AND _dom_start < _dom_end AND `repeat_day` BETWEEN _dom_start AND _dom_end)
            )
            /*
                Here's where I'm stuck..
               How do I check if a date range contains a
               4th Thursday of the month (repeat_nth_day = 4, repeat_weekday = 5)
            */
            /*
            (`repeat_nth_day` IS NULL OR `repeat_nth_day` = _nth_day) AND
            (`repeat_weekday` IS NULL OR `repeat_weekday` = _weekday)
            */
        )
    GROUP BY e.`event_id`;

END
`date_start` : "2016-01-01"
`date_end` : "2017-12-31"
`time_start` : NULL,
`time_end` : NULL,
`repeat_interval` : NULL
`repeat_year` : NULL
`repeat_month` : 2
`repeat_day` : 1
`repeat_nth_day` : NULL
`repeat_weekday` : NULL
REPEAT
    # events_filter_date inserts into the temporary table
    CALL events_filter_date(_date_cur);
    SET _date_cur = DATE_ADD(_date_cur, INTERVAL 1 DAY);
UNTIL _date_cur > _date_end
END REPEAT;

SELECT *
FROM `events_temp`;