【问题标题】:SQL Server Retrieving Recurring Appointments By DateSQL Server 按日期检索定期约会
【发布时间】:2010-09-27 13:25:06
【问题描述】:

我正在开发一个系统来存储约会和定期约会。我的架构是这样的

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

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

我保持循环类型简单且仅支持

Week Days,
Weekly,
4 Weekly,
52 Weekly

如果 RecurringType 为空,则该约会不会重复,RecurringEnd 也可以为空,如果它为空但 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

【问题讨论】:

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


    【解决方案1】:

    您需要将重复日期存储为日程表中的每一行。也就是说,您需要在初始保存时扩展重复日期。如果不这样做,就不可能(或极其困难)在您需要查看它们、检查冲突等时动态扩展它们。这将使所有约会工作相同,因为它们实际上都会在要加载的表等。我建议当用户指定他们的重复日期时,您让他们选择实际重复出现的次数。当您保存该定期约会时,将它们全部展开为表格中的单独行。您可以使用 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 循环等。如果您需要帮助,请询问。关键是将它们保存为表格中的常规行,这样您就不需要在每次需要显示或评估它们时即时展开它们。

    【讨论】:

    • 我试图避免这种情况,因为您的数据仅在您决定生成数据的未来范围内才是准确的。不过可能需要重新审视。
    【解决方案2】:

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

            --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)) 
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      相关资源
      最近更新 更多