2009-11-26 2 views
3

Я бы хотел, чтобы мои пользователи настраивали расписание для своих событий. Это может быть один день, или для удобства я бы хотел, чтобы они указывали повторное событие (похожее на встречу Outlook).Как хранить и запрашивать данные расписания?

Для одного события кажется, довольно легко (псевдо-код):

Просто есть столбец DateOfEvent, который имеет дату на нем.

Чтобы захватить будущие события:

Select * от событий, где DateOfEvent> {} DateTime.Now

Но как я мог хранить и запрашивать повторяющиеся события? Мне не нужно делать раз, потому что я просто хранили это отдельно, и если бы они нуждались в другом времени, я бы просто создал их еще одно событие. Так что не: Каждый Среде в 5 и четверги на 3.

Примеры:

Каждый Пн, Вт, Ср, Чт, Пт, каждую неделю

Каждый ср каждую неделю

Каждый второй вторник месяца

Что я использовал для запроса

Я добавил начальную и конечную даты. Если пользователь выбрал одну дату, я установил дату начала и окончания на выбранную дату. Мне просто пришлось немного изменить код ответа.

DECLARE 
    @StartDate SMALLDATETIME, 
    @EndDate SMALLDATETIME; 

SELECT 
    @StartDate = '20091129', 
    @EndDate = '20101220'; 

SELECT 
    d.CurrentDate, 
    m.* 
FROM 
    Calendar AS d 
    INNER JOIN Meet AS m 
    ON 
    (
     (d.CurrentDate = m.StartDate AND d.CurrentDate = m.EndDate) 
     OR d.DaysOfTheMonth = m.DayOfTheMonth 
     OR (d.DaysOfTheWeek = m.DayOfTheWeek AND COALESCE(m.WeekOfTheMonth, d.WeekOfTheMonth) = d.WeekOfTheMonth) 
     OR d.DaysOfTheWeek IN (1,7) AND m.OnWeekends = 1 
     OR d.DaysOfTheWeek BETWEEN 2 AND 6 AND m.OnWeekDays = 1 
    ) 
    -- now you can inner join to the event table 
    -- to list the name, other details, etc. 
    WHERE 
     d.CurrentDate BETWEEN @StartDate AND @EndDate 
     AND d.CurrentDate BETWEEN m.StartDate AND m.EndDate 
     ORDER BY d.CurrentDate; 

GO 

Заполнение таблицы Calandar:

INSERT dbo.Calendar(CurrentDate, DaysOfTheMonth, DaysOfTheWeek, WeekOfTheMonth, IsWeekDay, Even) 

    SELECT 
    CurrentDate, DaysOfTheMonth, DaysOfTheWeek, 
    WeekOfTheMonth = DATEDIFF(WEEK, DATEADD(DAY, 1-DaysOfTheMonth, CurrentDate), CurrentDate) + 1, 
    CASE WHEN DaysOfTheWeek IN (1, 7) THEN 0 ELSE 1 END AS IsWeekDay, 
    CASE WHEN w % 2 = 1 THEN 0 ELSE 1 END AS Even 
    FROM 
    (
     SELECT 
     CurrentDate, 
     DaysOfTheMonth = DATEPART(DAY, CurrentDate), 
     DaysOfTheWeek = DATEPART(WEEKDAY, CurrentDate), 
     w = DATEPART(WEEK, CurrentDate) 
     FROM 
     (
     SELECT CurrentDate = DATEADD(DAY, n-1, '20141001') 
     FROM 
     (
      SELECT TOP 900 
      n = ROW_NUMBER() OVER (ORDER BY c1.[object_id]) 
      FROM sys.all_columns AS c1 
      CROSS JOIN sys.all_columns AS c2 
      ORDER BY n 
     ) AS x) AS y) AS z; 
+0

Примечание: ВСТАВИТЬ dbo.Calendar (дт, де, с.в., MW, WD, даже) ВЫБОР дта, дх, мощность (2, DW-1), ... случая, когда ш% 2 = 1 ТОГДА 0 ИНАЧЕ 1 КОНЕЦ ОТ ( ВЫБОР ... ш = DATEPART (неделя, дт) – rball

+0

Примечания: SELECT d.dt, e.EventID календарные КАК д INNER JOIN EventSchedule КАК е НА d.dt = e.EventDate ИЛИ d.dm = e.DayOfMonth ИЛИ e.DayOfWeek & d.dw = d.dw И COALESCE (e.WeekOfMonth, d.mw) = d.mw И COALESCE (e.Even, d.even) = d.even OR d.dw IN (1, 7) И e.Weeken ds = 1 ИЛИ d.dw МЕЖДУ 2 И 6 И e.Weekdays = 1 – rball

+0

Вышеуказанные два комментария позволяют мне делать «каждую неделю» и конденсировать dayOfWeek из нескольких записей в день, выбранных до одной записи на каждое событие. Я могу опубликовать остальную часть кода, если кому-то еще интересно, иначе вы, вероятно, можете понять это из вышесказанного. – rball

ответ

4

Вы могли бы сделать что-то вроде этого:

CREATE TABLE dbo.EventSchedule 
(
    EventID INT,   -- FOREIGN KEY to event details 
    EventDate SMALLDATETIME, -- if one-time event 
    DayOfMonth TINYINT,  -- if once a month, e.g. 3rd of every month 
    DayOfWeek TINYINT,  -- if once a week, e.g. every Tuesday = 3 
    WeekDays BIT,   -- if only on weekdays, e.g. 1 = mon-fri 
    Weekends BIT,   -- if only on weekends, e.g. 1 = sat-sun 

    -- the next two are combined, e.g. 2/2 = 2nd Monday of each month 
    MonthlyInstance TINYINT, 
    MonthlyWeekday TINYINT 
); 

Итак, если вы хотите, чтобы найти все события, запланированные произойдет на определенную дату, вы можете сделать:

DECLARE 
    @dt SMALLDATETIME, 
    @dm TINYINT, 
    @dw TINYINT, 
    @inst TINYINT; 

SELECT 
    @dt = '20091201', 
    @dm = DATEPART(DAY, @dt) 
    @dw = DATEPART(WEEKDAY, @dt), 
    @inst = DATEDIFF(WEEK, DATEADD(DAY, [email protected], @dt), @dt) + 1; 

SELECT EventID 
    FROM dbo.EventSchedule 
    WHERE EventDate = @dt 
    OR DayOfMonth = @dm 
    OR DayOfWeek = @dw 
    OR (Weekdays = 1 AND @dw BETWEEN 2 AND 6) 
    OR (Weekends = 1 AND @dw IN (1,7)) 
    OR (MonthlyInstance = @inst AND MonthlyWeekday = @dw); 

Это непроверенный (я отправляю с Mac на день благодарения, в конце концов), и полагается на SET DATEFIRST быть default (где Sunday = 1, Monday = 2 и т. д.). Я также не уверен на 100% во второй части вторника, так как это, вероятно, нуждается в дополнительной математике в зависимости от дня недели в первый день месяца. Но я думал, что это может дать вам начало для других частей, и я вернусь и перейду, когда у меня появится шанс.

Для некоторых гораздо более сложных вариантов, см: http://www.codeproject.com/KB/database/sqlscheduleselector.aspx

А вот более полный пример, с населенной таблицы календаря, некоторые примеры событий разных типов, а также запрос, который извлекает все из ожидаемых событий данных диапазон дат.

CREATE DATABASE test; 
GO 
USE test; 
GO 

SET NOCOUNT ON; 
GO 

CREATE TABLE dbo.Calendar 
(
    dt SMALLDATETIME PRIMARY KEY, 
    dm TINYINT, 
    dw TINYINT, 
    mw TINYINT, 
    wd BIT 
); 
GO 

-- populate the table with the days from 2009 
-- (you will want more obviously; change TOP or add WHERE) 

INSERT dbo.Calendar(dt, dm, dw, mw, wd) 
    SELECT 
    dt, dm, dw, 
    mw = DATEDIFF(WEEK, DATEADD(DAY, 1-dm, dt), dt) + 1, 
    CASE WHEN dw IN (1, 7) THEN 0 ELSE 1 END 
    FROM 
    (
     SELECT 
     dt, 
     dm = DATEPART(DAY, dt), 
     dw = DATEPART(WEEKDAY, dt) 
     FROM 
     (
     SELECT dt = DATEADD(DAY, n-1, '20090101') 
     FROM 
     (
      SELECT TOP 365 
      n = ROW_NUMBER() OVER (ORDER BY c1.[object_id]) 
      FROM sys.all_columns AS c1 
      CROSS JOIN sys.all_columns AS c2 
      ORDER BY n 
     ) AS x) AS y) AS z; 
GO 

-- create your schedule table: 

CREATE TABLE dbo.EventSchedule 
(
    EventID  INT,   -- FOREIGN KEY to event details 
    EventDate SMALLDATETIME, -- if one-time event 
    [DayOfMonth] TINYINT,  -- if once a month, e.g. 3rd of every month 
    [DayOfWeek] TINYINT,  -- if once a week, e.g. every Tuesday = 3 
    Weekdays  BIT,   -- if only on weekdays, e.g. 1 = mon-fri 
    Weekends  BIT,   -- if only on weekends, e.g. 1 = sat-sun 
           -- if you want every day, set Weekdays+Weekends = 1 
    WeekOfMonth TINYINT  -- if only the nth Tuesday etc. 
); 

-- create some events: 
INSERT dbo.EventSchedule 
(
    EventID, 
    EventDate, 
    [DayOfMonth], 
    [DayOfWeek], 
    Weekdays, 
    Weekends, 
    WeekOfMonth 
) 
-- one on Jan 5th: 
    SELECT 1, '20090105', NULL, NULL, NULL, NULL, NULL 

-- one on the 3rd of every month: 
    UNION ALL SELECT 2, NULL, 3, NULL, NULL, NULL, NULL 

-- one every Tuesday: 
    UNION ALL SELECT 3, NULL, NULL, 3, NULL, NULL, NULL 

-- one the 2nd Wednesday of each month: 
    UNION ALL SELECT 4, NULL, NULL, 4, NULL, NULL, 2 

-- one only on weekends: 
    UNION ALL SELECT 5, NULL, NULL, NULL, NULL, 1, NULL 

-- one only on weekdays: 
    UNION ALL SELECT 6, NULL, NULL, NULL, 1, NULL, NULL; 

-- now, we have 6 events, some of which will happen 
-- multiple times in any given date range. So let's 
-- try it: 

DECLARE 
    @StartDate SMALLDATETIME, 
    @EndDate SMALLDATETIME; 

SELECT 
    @StartDate = '20090101', 
    @EndDate = '20090108'; 

SELECT 
    d.dt, 
    e.EventID 
FROM 
    dbo.Calendar AS d 
    INNER JOIN dbo.EventSchedule AS e 
    ON 
    (
     d.dt = e.EventDate 
     OR d.dm = e.[DayOfMonth] 
     OR (d.dw = e.[DayOfWeek] AND COALESCE(e.WeekOfMonth, d.mw) = d.mw) 
     OR d.dw IN (1,7) AND e.Weekends = 1 
     OR d.dw BETWEEN 2 AND 6 AND e.Weekdays = 1 
    ) 
    -- now you can inner join to the event table 
    -- to list the name, other details, etc. 
    WHERE 
     d.dt BETWEEN @StartDate AND @EndDate 
     ORDER BY d.dt, e.EventID; 

GO 

DROP TABLE dbo.Calendar, dbo.EventSchedule; 
GO 

USE [master]; 
GO 

DROP DATABASE test; 
GO 
+0

Выглядит круто, похоже, что он будет работать для первых двух просто отлично. – rball

+0

Я думаю, что единственная проблема заключается в том, как мне сопоставить событие с фактической датой? Скажите, что у меня есть представление о следующей неделе, как бы я узнал, какие дни показывать с указанным выше предложением? Я думаю, что это покажет, что есть событие на следующей неделе, но не конкретные дни - по крайней мере, я думаю ... – rball

+0

Возможно, вы могли бы использовать таблицу календаря? Позвольте мне добавить к моему ответу. –

0

Мы создали sql'server работу, которая периодически (смотрит на вас утверждают, ежечасно достаточно) называют некоторые хранимую процедуру. В другом направлении эта процедура выбирает 2 вещи:

  1. расчетное событие NEXT на основе некоторой рекурсивной информации из таблицы [A]. И место это событие в таблицу [B]
  2. Выбор готов к стрельбе события из таблицы [B]
+0

Почасово было бы хорошо, но я не думаю, что это так сложно, и мне не нужно ничего запускать, но вместо этого есть способ увидеть все события за период дат, а не только первый. – rball

3

Для хранения графика, посмотрите на моем ответ на этот вопросе

What is the best way to represent "Recurring Events" in database?

Здесь я описываю, как SQL Server хранит расписание информации в своих sysschedules и связанных таблицах. У них действительно красивый дизайн схемы, который поддерживает все случаи планирования, о которых вы спрашиваете. Документация по MSDN также очень полезна.

Чтобы получить все сроки расписания между диапазоном дат для отображения типа внешнего вида, просмотрите блог Peter Larsson, он создал отличный sproc для расчета этих значений.

CREATE PROCEDURE dbo.uspGetScheduleTimes 
    (
    @startDate DATETIME, 
    @endDate DATETIME 
) 
    AS 
    /* 
    This code is blogged here 
    http://weblogs.sqlteam.com/peterl/archive/2008/10/10/Keep-track-of-all-your-jobs-schedules.aspx 
    */ 
    SET NOCOUNT ON 

    -- Create a tally table. If you already have one of your own please use that instead. 
    CREATE TABLE #tallyNumbers 
     (
      num SMALLINT PRIMARY KEY CLUSTERED 
     ) 

    DECLARE  @index SMALLINT 

    SET @index = 1 

    WHILE @index <= 8640 
    BEGIN 
     INSERT #tallyNumbers 
      (
      num 
     ) 
     VALUES (
      @index 
     ) 

     SET @index = @index + 1 
    END 

    -- Create a staging table for jobschedules 
    CREATE TABLE #jobSchedules 
     (
      rowID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED, 
      serverName SYSNAME NOT NULL, 
      jobName SYSNAME NOT NULL, 
      jobDescription NVARCHAR(512) NOT NULL, 
      scheduleName SYSNAME NOT NULL, 
      scheduleID INT NOT NULL, 
      categoryName SYSNAME NOT NULL, 
      freq_type INT NOT NULL, 
      freq_interval INT NOT NULL, 
      freq_subday_type INT NOT NULL, 
      freq_subday_interval INT NOT NULL, 
      freq_relative_interval INT NOT NULL, 
      freq_recurrence_factor INT NOT NULL, 
      startDate DATETIME NOT NULL, 
      startTime DATETIME NOT NULL, 
      endDate DATETIME NOT NULL, 
      endTime DATETIME NOT NULL, 
      jobEnabled INT NOT NULL, 
      scheduleEnabled INT NOT NULL 
     ) 

    /* 
    -- Popoulate the staging table for JobSchedules with SQL Server 2000 
    INSERT  #jobSchedules 
     (
      serverName, 
      jobName, 
      jobDescription, 
      scheduleName, 
      scheduleID, 
      categoryName, 
      freq_type, 
      freq_interval, 
      freq_subday_type, 
      freq_subday_interval, 
      freq_relative_interval, 
      freq_recurrence_factor, 
      startDate, 
      startTime, 
      endDate, 
      endTime, 
      jobEnabled, 
      scheduleEnabled 
     ) 
    SELECT  sj.originating_server, 
     sj.name, 
     COALESCE(sj.description, ''), 
     sjs.name, 
     sjs.schedule_id, 
     sc.name, 
     sjs.freq_type, 
     sjs.freq_interval, 
     sjs.freq_subday_type, 
     sjs.freq_subday_interval, 
     sjs.freq_relative_interval, 
     sjs.freq_recurrence_factor, 
     COALESCE(STR(sjs.active_start_date, 8), CONVERT(CHAR(8), GETDATE(), 112)), 
     STUFF(STUFF(REPLACE(STR(sjs.active_start_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':'), 
     STR(sjs.active_end_date, 8), 
     STUFF(STUFF(REPLACE(STR(sjs.active_end_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':'), 
     sj.enabled, 
     sjs.enabled 
    FROM   msdb..sysjobschedules AS sjs 
    INNER JOIN msdb..sysjobs AS sj ON sj.job_id = sjs.job_id 
    INNER JOIN msdb..syscategories AS sc ON sc.category_id = sj.category_id 
    WHERE   sjs.freq_type IN (1, 4, 8, 16, 32) 
    ORDER BY  sj.originating_server, 
     sj.name, 
     sjs.name 
    */ 

    -- Popoulate the staging table for JobSchedules with SQL Server 2005 and SQL Server 2008 
    INSERT  #JobSchedules 
     (
      serverName, 
      jobName, 
      jobDescription, 
      scheduleName, 
      scheduleID, 
      categoryName, 
      freq_type, 
      freq_interval, 
      freq_subday_type, 
      freq_subday_interval, 
      freq_relative_interval, 
      freq_recurrence_factor, 
      startDate, 
      startTime, 
      endDate, 
      endTime, 
      jobEnabled, 
      scheduleEnabled 
     ) 
    SELECT  srv.srvname, 
     sj.name, 
     COALESCE(sj.description, ''), 
     ss.name, 
     ss.schedule_id, 
     sc.name, 
     ss.freq_type, 
     ss.freq_interval, 
     ss.freq_subday_type, 
     ss.freq_subday_interval, 
     ss.freq_relative_interval, 
     ss.freq_recurrence_factor, 
     COALESCE(STR(ss.active_start_date, 8), CONVERT(CHAR(8), GETDATE(), 112)), 
     STUFF(STUFF(REPLACE(STR(ss.active_start_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':'), 
     STR(ss.active_end_date, 8), 
     STUFF(STUFF(REPLACE(STR(ss.active_end_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':'), 
     sj.enabled, 
     ss.enabled 
    FROM   msdb..sysschedules AS ss 
    INNER JOIN msdb..sysjobschedules AS sjs ON sjs.schedule_id = ss.schedule_id 
    INNER JOIN msdb..sysjobs AS sj ON sj.job_id = sjs.job_id 
    INNER JOIN sys.sysservers AS srv ON srv.srvid = sj.originating_server_id 
    INNER JOIN msdb..syscategories AS sc ON sc.category_id = sj.category_id 
    WHERE   ss.freq_type IN(1, 4, 8, 16, 32) 
    ORDER BY  srv.srvname, 
     sj.name, 
     ss.name 

    -- Only deal with jobs that has active start date before @endDate 
    DELETE 
    FROM #JobSchedules 
    WHERE startDate > @endDate 

    -- Only deal with jobs that has active end date after @startDate 
    DELETE 
    FROM #JobSchedules 
    WHERE endDate < @startDate 

    -- Deal with first, second, third, fourth and last occurence 
    DECLARE  @tempStart DATETIME, 
    @tempEnd DATETIME 

    SELECT @tempStart = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', @startDate), '19000101'), 
    @TempEnd = DATEADD(MONTH, DATEDIFF(MONTH, '18991231', @endDate), '18991231') 

    CREATE TABLE #dayInformation 
     (
      infoDate DATETIME PRIMARY KEY CLUSTERED, 
      weekdayName VARCHAR(9) NOT NULL, 
      statusCode INT NOT NULL, 
      lastDay TINYINT DEFAULT 0 
     ) 

    WHILE @tempStart <= @tempEnd 
    BEGIN 
     INSERT #dayInformation 
      (
      infoDate, 
      weekdayName, 
      statusCode 
     ) 
     SELECT @tempStart, 
      DATENAME(WEEKDAY, @tempStart), 
      CASE 
      WHEN DATEPART(DAY, @tempStart) BETWEEN 1 AND 7 THEN 1 
      WHEN DATEPART(DAY, @tempStart) BETWEEN 8 AND 14 THEN 2 
      WHEN DATEPART(DAY, @tempStart) BETWEEN 15 AND 21 THEN 4 
      WHEN DATEPART(DAY, @tempStart) BETWEEN 22 AND 28 THEN 8 
      ELSE 0 
      END 

     SET @tempStart = DATEADD(DAY, 1, @tempStart) 
    END 

    UPDATE  di 
    SET   di.statusCode = di.statusCode + 16 
    FROM   #dayInformation AS di 
    INNER JOIN (
      SELECT  DATEDIFF(MONTH, '19000101', infoDate) AS theMonth, 
       DATEPART(DAY, MAX(infoDate)) - 6 AS theDay 
      FROM   #dayInformation 
      GROUP BY  DATEDIFF(MONTH, '19000101', infoDate) 
     ) AS x ON x.theMonth = DATEDIFF(MONTH, '19000101', di.infoDate) 
    WHERE   DATEPART(DAY, di.infoDate) >= x.theDay 

    UPDATE  di 
    SET   di.lastDay = 16 
    FROM   #dayInformation AS di 
    INNER JOIN (
      SELECT  DATEDIFF(MONTH, '19000101', infoDate) AS theMonth, 
       MAX(infoDate) AS theDay 
      FROM   #dayInformation 
      GROUP BY  DATEDIFF(MONTH, '19000101', infoDate) 
     ) AS x ON x.theMonth = DATEDIFF(MONTH, '19000101', di.infoDate) 
    WHERE   di.infoDate = x.theDay 

    UPDATE #dayInformation 
    SET lastDay = DATEPART(DAY, infoDate) 
    WHERE DATEPART(DAY, infoDate) BETWEEN 1 AND 4 

    -- Stage all individual schedule times 
    CREATE TABLE #scheduleTimes 
     (
      rowID INT NOT NULL, 
      infoDate DATETIME NOT NULL, 
      startTime DATETIME NOT NULL, 
      endTime DATETIME NOT NULL, 
      waitSeconds INT DEFAULT 0 
     ) 

    CREATE CLUSTERED INDEX IX_rowID ON #scheduleTimes(rowID) 

    -- Insert one time only schedules 
    INSERT #scheduleTimes 
    (
     rowID, 
     infoDate, 
     startTime, 
     endTime 
    ) 
    SELECT rowID, 
    startDate, 
    startTime, 
    endTime 
    FROM #jobSchedules 
    WHERE freq_type = 1 
    AND startDate >= @StartDate 
    AND startDate <= @EndDate 

    -- Insert daily schedules 
    INSERT  #scheduleTimes 
     (
      rowID, 
      infoDate, 
      startTime, 
      endTime, 
      waitSeconds 
     ) 
    SELECT  js.rowID, 
     di.infoDate, 
     js.startTime, 
     js.endTime, 
     CASE js.freq_subday_type 
      WHEN 1 THEN 0 
      WHEN 2 THEN js.freq_subday_interval 
      WHEN 4 THEN 60 * js.freq_subday_interval 
      WHEN 8 THEN 3600 * js.freq_subday_interval 
     END 
    FROM   #jobSchedules AS js 
    INNER JOIN #dayInformation AS di ON di.infoDate >= @startDate 
      AND di.infoDate <= @endDate 
    WHERE   js.freq_type = 4 
     AND DATEDIFF(DAY, js.startDate, di.infoDate) % js.freq_interval = 0 

    -- Insert weekly schedules 
    INSERT  #scheduleTimes 
     (
      rowID, 
      infoDate, 
      startTime, 
      endTime, 
      waitSeconds 
     ) 
    SELECT  js.rowID, 
     di.infoDate, 
     js.startTime, 
     js.endTime, 
     CASE js.freq_subday_type 
      WHEN 1 THEN 0 
      WHEN 2 THEN js.freq_subday_interval 
      WHEN 4 THEN 60 * js.freq_subday_interval 
      WHEN 8 THEN 3600 * js.freq_subday_interval 
     END 
    FROM   #jobSchedules AS js 
    INNER JOIN #dayInformation AS di ON di.infoDate >= @startDate 
      AND di.infoDate <= @endDate 
    WHERE   js.freq_type = 8 
     AND 1 =  CASE 
      WHEN js.freq_interval & 1 = 1 AND di.weekdayName = 'Sunday' THEN 1 
      WHEN js.freq_interval & 2 = 2 AND di.weekdayName = 'Monday' THEN 1 
      WHEN js.freq_interval & 4 = 4 AND di.weekdayName = 'Tuesday' THEN 1 
      WHEN js.freq_interval & 8 = 8 AND di.weekdayName = 'Wednesday' THEN 1 
      WHEN js.freq_interval & 16 = 16 AND di.weekdayName = 'Thursday' THEN 1 
      WHEN js.freq_interval & 32 = 32 AND di.weekdayName = 'Friday' THEN 1 
      WHEN js.freq_interval & 64 = 64 AND di.weekdayName = 'Saturday' THEN 1 
      ELSE 0 
      END 
     AND(DATEDIFF(DAY, js.startDate, di.infoDate)/7) % js.freq_recurrence_factor = 0 

    -- Insert monthly schedules 
    INSERT  #scheduleTimes 
     (
      rowID, 
      infoDate, 
      startTime, 
      endTime, 
      waitSeconds 
     ) 
    SELECT  js.rowID, 
     di.infoDate, 
     js.startTime, 
     js.endTime, 
     CASE js.freq_subday_type 
      WHEN 1 THEN 0 
      WHEN 2 THEN js.freq_subday_interval 
      WHEN 4 THEN 60 * js.freq_subday_interval 
      WHEN 8 THEN 3600 * js.freq_subday_interval 
     END 
    FROM   #jobSchedules AS js 
    INNER JOIN #dayInformation AS di ON di.infoDate >= @startDate 
      AND di.infoDate <= @endDate 
    WHERE   js.freq_type = 16 
     AND DATEPART(DAY, di.infoDate) = js.freq_interval 
     AND DATEDIFF(MONTH, js.startDate, di.infoDate) % js.freq_recurrence_factor = 0 

    -- Insert monthly relative schedules 
    INSERT  #scheduleTimes 
     (
      rowID, 
      infoDate, 
      startTime, 
      endTime, 
      waitSeconds 
     ) 
    SELECT  js.rowID, 
     di.infoDate, 
     js.startTime, 
     js.endTime, 
     CASE js.freq_subday_type 
      WHEN 1 THEN 0 
      WHEN 2 THEN js.freq_subday_interval 
      WHEN 4 THEN 60 * js.freq_subday_interval 
      WHEN 8 THEN 3600 * js.freq_subday_interval 
     END 
    FROM   #jobSchedules AS js 
    INNER JOIN #dayInformation AS di ON di.infoDate >= @startDate 
      AND di.infoDate <= @endDate 
    WHERE   js.freq_type = 32 
     AND 1 =  CASE 
      WHEN js.freq_interval = 1 AND di.weekdayName = 'Sunday' THEN 1 
      WHEN js.freq_interval = 2 AND di.weekdayName = 'Monday' THEN 1 
      WHEN js.freq_interval = 3 AND di.weekdayName = 'Tuesday' THEN 1 
      WHEN js.freq_interval = 4 AND di.weekdayName = 'Wednesday' THEN 1 
      WHEN js.freq_interval = 5 AND di.weekdayName = 'Thursday' THEN 1 
      WHEN js.freq_interval = 6 AND di.weekdayName = 'Friday' THEN 1 
      WHEN js.freq_interval = 7 AND di.weekdayName = 'Saturday' THEN 1 
      WHEN js.freq_interval = 8 AND js.freq_relative_interval = di.lastDay THEN 1 
      WHEN js.freq_interval = 9 AND di.weekdayName NOT IN('Sunday', 'Saturday') THEN 1 
      WHEN js.freq_interval = 10 AND di.weekdayName IN('Sunday', 'Saturday') THEN 1 
      ELSE 0 
      END 
     AND di.statusCode & js.freq_relative_interval = js.freq_relative_interval 
     AND DATEDIFF(MONTH, js.startDate, di.infoDate) % js.freq_recurrence_factor = 0 

    -- Get the daily recurring schedule times 
    INSERT  #scheduleTimes 
     (
      rowID, 
      infoDate, 
      startTime, 
      endTime, 
      waitSeconds 
     ) 
    SELECT  st.rowID, 
     st.infoDate, 
     DATEADD(SECOND, tn.num * st.waitSeconds, st.startTime), 
     st.endTime, 
     st.waitSeconds 
    FROM   #scheduleTimes AS st 
    CROSS JOIN #tallyNumbers AS tn 
    WHERE   tn.num * st.waitSeconds <= DATEDIFF(SECOND, st.startTime, st.endTime) 
     AND st.waitSeconds > 0 

    -- Present the result 
    SELECT  js.scheduleID, 
     js.serverName, 
     js.jobName, 
     js.jobDescription, 
     js.scheduleName, 
     js.categoryName, 
     st.infoDate, 
     st.startTime, 
     st.endTime, 
     js.jobEnabled, 
     js.scheduleEnabled 
    FROM   #scheduleTimes AS st 
    INNER JOIN #jobSchedules AS js ON js.rowID = st.rowID 

    -- Clean up 
    DROP TABLE #jobSchedules, 
     #dayInformation, 
     #scheduleTimes, 
     #tallyNumbers 

Для получения значимого краткое описание графика, как «каждый понедельник в 2:00 вечера», посмотрите на sp_get_schedule_description sproc.

+0

Опять же, довольно круто, но как, черт возьми, я вижу внешний вид самих дат?Например, как бы я запросил, чтобы показать все события, которые появятся в ближайшие две недели. – rball

+0

Спасибо, много информации здесь, позвольте мне проверить это, и я вернусь к вам. Очень признателен. – rball

Смежные вопросы