SQL日期/时间操作

SQL日期/时间操作,sql,sql-server,date,time,schedule,Sql,Sql Server,Date,Time,Schedule,所以我有一组特定天数的小时,我们称之为时间表,这个时间表描述了一般模式。然而,偶尔也会有一些我将称之为例外的情况,在这些情况下,时间表会增长或受到限制 例如: 周一的日程安排为上午7:00-下午4:00、下午5:00-9:00 特别是下周一的例外情况:下午6:00-7:00 可以操纵SQL查询中的小时数以返回7:00am-4:00PM、5:00-6:00PM和7:00PM-9:00PM吗。我意识到使用一个临时表和大约三个不同的查询是可能的,但我希望能做得更优雅一些 另一个选择可能是在C逻辑中完成

所以我有一组特定天数的小时,我们称之为时间表,这个时间表描述了一般模式。然而,偶尔也会有一些我将称之为例外的情况,在这些情况下,时间表会增长或受到限制

例如:

周一的日程安排为上午7:00-下午4:00、下午5:00-9:00

特别是下周一的例外情况:下午6:00-7:00

可以操纵SQL查询中的小时数以返回7:00am-4:00PM、5:00-6:00PM和7:00PM-9:00PM吗。我意识到使用一个临时表和大约三个不同的查询是可能的,但我希望能做得更优雅一些

另一个选择可能是在C逻辑中完成这一切。。。我将非常感谢您对这个日程安排问题的任何帮助

源表请注意,我仍然愿意在必要时更改结构

Schedule - A user can set up a named schedule
Id
Name


ScheduleDates - Describes the dates range(s) a schedule is active
Id
ScheduleId
StartDate
EndDate


ScheduleEntries - Describe the schedule that describes most 
of the dates in the schedule
ScheduleId
StartTime
EndTime
DayId (Describes which day of the week)


Exception
Id
Reason
StartTime
EndTime 

请把你的建议放在你已经计算过的地方,我们肯定能在这方面做出贡献。我的建议仍然是创建一个proc,使用Getdate函数,创建一个algo来检查这个时间是否属于您的异常。其余的我相信你能猜到。

这是我为我的具体案例提出的建议。我决定,我只想收回所有信息,这样我就可以告诉用户一些关于时间的特殊信息

DECLARE @start DATE = '12-25-2013'
DECLARE @end DATE = '1-31-2014'

;WITH [DateIt] AS -- Explodes the dates between start and end inclusive
(
    SELECT
        @start AS [sd],
        DATENAME(dw, @start) AS [dt],
        DATEPART(dw, @start) AS [dw]
    UNION ALL
    SELECT
        DATEADD(DAY, 1, sd),
        DATENAME(dw, DATEADD(DAY, 1, sd)) AS [dt],
        DATEPART(dw, DATEADD(DAY, 1, sd)) AS [dw]
    FROM
        [DateIt] [di]
    WHERE
        sd < @end
)

SELECT --DISTINCT -- May need distinct here
    [di].[sd] AS [Date],
    --[di].[dw] AS [DayNumber],
    --[di].[dt] AS [DayName],

    [s].[Id] AS [ScheduleId],
    [s].[Name] AS [ScheduleName],

    [se].[LocationId],

    [se].[StartTime],
    [se].[EndTime],

    0 AS [ExceptionState] -- Normal Schedule
FROM
    [DateIt] [di]
    INNER JOIN [campusHours].[ScheduleEntries] [se] ON [di].[dw] = [se].[DayId]
    INNER JOIN [campusHours].[Schedule] [s] ON [s].[Id] = [se].[ScheduleId]
    --INNER JOIN [campusHours].[ScheduleDates] [sd] ON [sd].[ScheduleId] = [s].[Id]
WHERE
    EXISTS
    (
        SELECT
            1
        FROM
            [campusHours].[ScheduleDates] sd
        WHERE
            -- Choose the valid schedule
            [di].[sd] BETWEEN sd.[StartDate] AND sd.[EndDate]
            AND
            -- Don't take days from a different schedule
            s.[Id] = sd.[ScheduleId]
    )
UNION ALL -- We are going to add in the exceptions
SELECT
    [di].[sd] AS [Date],
    --[di].[dw] AS [DayNumber],
    --[di].[dt] AS [DayName],

    0 AS [ScheduleId], -- Represents that we aren't a schedule, could use NULL if you like
    'Exception' AS [ScheduleName],

    [e].[LocationId],

    [e].[StartTime],
    [e].[EndTime],

    CASE WHEN [e].[IsContraction] = 1 THEN 1 ELSE 2 END AS [ExceptionState] -- 1 is contraction, 2 is extension
FROM
    [DateIt] [di]
    INNER JOIN [campusHours].[Exception] [e] ON [di].[sd] = [e].[StartDate]
ORDER BY
    [di].[sd], [LocationId], [se].[StartTime]

描述您的源表。您的字段只是日期还是日期时间?我这样问是因为如果字段是datetime,则不需要表ScheduleEntries。您已经有了StartDate上的日期是否仅适用于特定的ScheduleEntry?如果是这样,我会在ScheduleEntry表中添加一个Id字段,并在Exception中添加一个对ScheduleId的外键引用。我还将向Exception添加一个DayId字段。然后,您可以将join ScheduleEntries保留在异常上,并将其用作覆盖。看起来CTE集合可能能够处理它。您是否可以编辑您的问题,以包括每列的数据类型以及一些示例输入和结果行?是否要为特定计划或所有计划生成结果?是默认为100的查询提示。如果在查询中指定MAXRECURSION 0,则递归是无限的。