SQL-带异常的重复日历事件

SQL-带异常的重复日历事件,sql,database-design,calendar,schedule,Sql,Database Design,Calendar,Schedule,我正在寻找一些关于使用重复事件的日历的最佳实践的建议 假设我有一个带有字段的表“event” id info id event_id start_date end_date interval 和另一个表“event_meta” 与田野 id info id event_id start_date end_date interval 我可以创建一个重复事件,如下所示 活动: id | info --------------- 1 | some info 事件元 id | even

我正在寻找一些关于使用重复事件的日历的最佳实践的建议

假设我有一个带有字段的表“event”

id 
info
id
event_id
start_date
end_date
interval
和另一个表“event_meta” 与田野

id 
info
id
event_id
start_date
end_date
interval
我可以创建一个重复事件,如下所示

活动:

id | info
---------------
 1 | some info

事件元

id | event_Id | start_date | end_date | interval |
--------------------------------------------------
--------------------------------------------------
 1 |     1    | 2020-01-01 |2020-01-30|     7    |
--------------------------------------------------
 1 |     1    | 2020-01-03 |2020-01-30|     7    |
--------------------------------------------------
 1 |     1    | 2020-01-05 |2020-01-30|     7    |
--------------------------------------------------
每周三、周五和周日重复一次,直到月底

使用此查询:

SELECT * from event_meta
outer join event on event.id = event_meta.id
where (start_date - <todays date>) % interval = 0
and start_date <= <todays date>
and end_date >= <todays date>
我可以把那天的所有活动都拿来

当我需要为某些事件提供异常时,此系统会中断。例如,如果我想在模式中重新安排事件的一个实例,但其他实例保持不变,或者如果我想更新事件的模式,但不转移本应已发生的事件


有没有人对如何在这个模型中或在另一个模型上实现这一点有什么建议?

这就是我所做的:

我创建了一个事件表,如下所示:

| event_id | event_title | start_date | end_date | start_time | end_time | one_time_event | day_sunday | day_monday | day_tuesday | day_wednesday | day_thursday | day_friday | day_saturday | week_month | day_of_month | month_of_year | status | parent_event_id |
|----------|-------------|------------|----------|------------|----------|----------------|------------|------------|-------------|---------------|--------------|------------|--------------|------------|--------------|---------------|--------|-----------------|
| PK       |             |            |          |            |          | bool           | bool       | bool       | bool        | bool          | bool         | bool       | bool         |            |              |               | bool   | FK_TO_event_id  |
您可以使用此工具获取日期范围内的所有事件

DECLARE @startDate DATE = '2020-09-01';
DECLARE @endDate DATE = '2020-10-15';

WITH    AllDays AS
           ( SELECT   @startDate AS [Date]
               UNION ALL
               SELECT   DATEADD(DAY, 1, [Date])
               FROM     AllDays
               WHERE    [Date] < @endDate )
SELECT "FULL".Date + CAST(dbo.EventSlots.start_time AS smalldatetime) "DateTime", dbo.EventSlots.* FROM 
    (SELECT [Date], [event_id]
    FROM   AllDays 
    INNER JOIN [dbo].[EventSlots] 
    ON 
    ([dbo].[EventSlots].one_time_event=0 
        AND [dbo].[EventSlots].start_date<=AllDays.Date AND [dbo].[EventSlots].end_date>=AllDays.Date
        AND ( ([dbo].[EventSlots].day_sunday=1 and DATEPART(WEEKDAY, AllDays.Date)=1) OR ([dbo].[EventSlots].day_monday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=2) OR ([dbo].[EventSlots].day_tuesday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=3) OR ([dbo].[EventSlots].day_wednesday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=4) OR ([dbo].[EventSlots].day_thursday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=5) OR ([dbo].[EventSlots].day_friday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=6) OR ([dbo].[EventSlots].day_saturday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=7) OR ([dbo].[EventSlots].day_sunday=0 AND [dbo].[EventSlots].day_monday=0 AND [dbo].[EventSlots].day_tuesday=0 AND [dbo].[EventSlots].day_wednesday=0 AND [dbo].[EventSlots].day_thursday=0 AND [dbo].[EventSlots].day_friday=0 AND [dbo].[EventSlots].day_saturday=0))
        AND (([dbo].[EventSlots].week_month IS NOT NULL AND [dbo].[EventSlots].week_month=dbo.MONTHWEEK(AllDays.Date)) OR [dbo].[EventSlots].week_month IS NULL) 
        AND (([dbo].[EventSlots].day_of_month IS NOT NULL AND [dbo].[EventSlots].day_of_month=DATEPART(DAY, AllDays.Date)) OR [dbo].[EventSlots].day_of_month IS NULL)
        AND (([dbo].[EventSlots].month_of_year IS NOT NULL AND [dbo].[EventSlots].month_of_year=DATEPART(MONTH, AllDays.Date)) OR [dbo].[EventSlots].month_of_year IS NULL)
    )
    OR ([dbo].[EventSlots].one_time_event=1 AND [dbo].[EventSlots].start_date=AllDays.Date)
        EXCEPT
    SELECT Date
      ,[parent_event_id] "event_id"
      FROM AllDays
      INNER JOIN [dbo].[EventSlots] 
        ON 
        ([dbo].[EventSlots].one_time_event=0 
            AND [dbo].[EventSlots].start_date<=AllDays.Date AND [dbo].[EventSlots].end_date>=AllDays.Date
            AND ( ([dbo].[EventSlots].day_sunday=1 and DATEPART(WEEKDAY, AllDays.Date)=1) OR ([dbo].[EventSlots].day_monday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=2) OR ([dbo].[EventSlots].day_tuesday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=3) OR ([dbo].[EventSlots].day_wednesday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=4) OR ([dbo].[EventSlots].day_thursday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=5) OR ([dbo].[EventSlots].day_friday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=6) OR ([dbo].[EventSlots].day_saturday = 1 AND DATEPART(WEEKDAY, AllDays.Date)=7) OR ([dbo].[EventSlots].day_sunday=0 AND [dbo].[EventSlots].day_monday=0 AND [dbo].[EventSlots].day_tuesday=0 AND [dbo].[EventSlots].day_wednesday=0 AND [dbo].[EventSlots].day_thursday=0 AND [dbo].[EventSlots].day_friday=0 AND [dbo].[EventSlots].day_saturday=0))
            AND (([dbo].[EventSlots].week_month IS NOT NULL AND [dbo].[EventSlots].week_month=dbo.MONTHWEEK(AllDays.Date)) OR [dbo].[EventSlots].week_month IS NULL) 
            AND (([dbo].[EventSlots].day_of_month IS NOT NULL AND [dbo].[EventSlots].day_of_month=DATEPART(DAY, AllDays.Date)) OR [dbo].[EventSlots].day_of_month IS NULL)
            AND (([dbo].[EventSlots].month_of_year IS NOT NULL AND [dbo].[EventSlots].month_of_year=DATEPART(MONTH, AllDays.Date)) OR [dbo].[EventSlots].month_of_year IS NULL)
        )
        OR ([dbo].[EventSlots].one_time_event=1 AND [dbo].[EventSlots].start_date=AllDays.Date)
      WHERE dbo.EventSlots.parent_event_id IS NOT NULL
) AS "FULL"
INNER JOIN dbo.EventSlots ON "FULL".event_id = dbo.EventSlots.event_id

父事件id基本上是主事件的例外。使用减号,我们可以去掉那些被异常替换的

重复模式是如何工作的?首先,我们检查从CTE生成的日期是否与任何一个工作日匹配,然后检查一个月中的周数、一个月中的日期,然后检查一年中的月份。我还保留了一个条件,如果值为null,它将转到下一个


我知道代码很凌乱,但对于我的用例来说,它似乎工作得很好,我得到的列表是正确的

你需要一些例外的例子。不清楚你说的是什么意思。