SQL Server按日期检索重复约会

时间:2010-09-27 13:25:06

标签: sql-server sql-server-2005 stored-procedures

我正在研究一个存储约会和定期约会的系统。我的架构看起来像这样

Appointment
-----------
ID
Start
End
Title
RecurringType
RecurringEnd

RecurringTypes
---------------
Id
Name

我保持重复类型简单,只支持

Week Days,
Weekly,
4 Weekly,
52 Weekly

如果RecurringType为null,那么该约会不会重复,RecurringEnd也可以为空,如果它的null但是RecurringType是一个值,那么它将无限期地重复出现。我正在尝试编写一个存储过程来返回给定日期范围内的所有约会及其日期。

我已经让存储过程适用于非定期会议,但我正在努力找出返回复发的最佳方法,这是我到目前为止所拥有的

ALTER PROCEDURE GetAppointments
(
    @StartDate DATETIME,
    @EndDate DATETIME
)
AS

SELECT  
    appointment.id,
    appointment.title,
    appointment.recurringType,
    appointment.recurringEnd,
    appointment.start,
    appointment.[end]
FROM
    mrm_booking
WHERE
    (
        Start >= @StartDate AND
        [End] <= @EndDate
    ) 

我现在需要在where子句中添加以获取重复次数并更改select中返回的内容以返回正常会议的开始和结束日期以及计算的重复开始/结束日期。

关于处理此问题的最佳方法的任何指针都会很棒。我正在使用SQL Server 2005

2 个答案:

答案 0 :(得分:0)

您需要将定期日期存储为计划中的每一行。也就是说,您需要在初始保存时扩展重复日期。如果不这样做,当你需要看到它们,检查冲突等时,就不可能(或者极其困难)地扩展它们。这将使所有约会工作相同,因为它们实际上都会在我建议当用户指定他们的重复日期时,你会让他们选择实际的重复发生次数。当您去保存该定期约会时,将它们全部展开为表中的各个行。您可以将FK用于父约会行并将其链接为链接列表:

Appointment
-----------
ID
Start
End
Title
RecurringParentID  FK to ID

示例数据:

ID ....  RecurringParentID
1  ....  null
2  ....  1
3  ....  2
4  ....  3
5  ....  4

如果在定期约会时间表中间运行,比如说ID = 3,他们决定取消它们,你可以跟随链并删除剩余的ID = 3,4,5。

至于扩展日期,你可以使用CTE,数字表,while循环等,如果你需要帮助,只需要问。关键是将它们保存为表中的常规行,这样您就不需要在每次需要显示或评估它们时动态扩展它们。

答案 1 :(得分:0)

我最终通过在开始和结束日期之间创建每天的临时表以及它们各自的星期几来完成此操作。我将复发间隔限制为工作日和设定的周数,并添加到这样的子句

        --Check Week Days Reoccurrence
        (
            mrm_booking.repeat_type_id = 1 AND              
            #ValidWeeklyDayOfWeeks.dow IN (1,2,3,4,5)
        ) OR
        --Check Weekly Reoccurrence
        (
            mrm_booking.repeat_type_id = 2 AND
            DATEPART(WEEKDAY, mrm_booking.start_date) = #ValidWeeklyDayOfWeeks.dow
        ) OR
        --Check 4 Weekly Reoccurences
        (
            mrm_booking.repeat_type_id = 3 AND
            DATEDIFF(d,#ValidWeeklyDayOfWeeks.[Date],mrm_booking.start_date) % (7*4) = 0
        ) OR
        --Check 52 Weekly Reoccurences
        (
            mrm_booking.repeat_type_id = 4 AND
            DATEDIFF(d,#ValidWeeklyDayOfWeeks.[Date],mrm_booking.start_date) % (7*52) = 0
        )

如果您感兴趣我使用此

建立了一个开始日期和结束日期之间的表格
INSERT INTO #ValidWeeklyDayOfWeeks
--Get Valid Reoccurence Dates For Week Day Reoccurences
SELECT
    DATEADD(d, offset - 1, @StartDate) AS [Date],
    DATEPART(WEEKDAY,DATEADD(d, offset - 1, @StartDate)) AS Dow
FROM
    (
        SELECT ROW_NUMBER() OVER(ORDER BY s1.id) AS offset
        FROM syscolumns s1, syscolumns s2
    ) a WHERE offset <= DATEDIFF(d, @StartDate, DATEADD(d,1,@EndDate)) 

它不是很优雅,可能非常符合我的需要,但它完成了我需要它做的工作。