【问题标题】:How can I store and query schedule data?如何存储和查询计划数据?
【发布时间】:2010-12-20 17:58:54
【问题描述】:

我想让我的用户为他们的活动设置时间表。这可能是一天,或者为了方便起见,我想让他们指定一个重复发生的事件(类似于 Outlook 约会)。

对于单个事件,这似乎很容易(伪代码):

只要有一个包含日期的 DateOfEvent 列。

要抓住未来的事件:

从 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

填写日历表:

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;

【问题讨论】:

  • 注意:INSERT dbo.Calendar(dt, dm, dw, mw, wd, even) SELECT dt, dm, power(2, dw-1), ... CASE WHEN w % 2 = 1 THEN 0 ELSE 1 END FROM ( SELECT ... w = DATEPART(WEEK, dt)
  • 注意:从日历中选择 d.dt、e.EventID AS d INNER JOIN EventSchedule AS e ON d.dt = e.EventDate OR d.dm = e.DayOfMonth OR e.DayOfWeek & d。 dw = d.dw AND COALESCE (e.WeekOfMonth, d.mw) = d.mw AND COALESCE (e.Even, d.even) = d.even OR d.dw IN (1, 7) AND e.Weekends = 1 OR d.dw BETWEEN 2 AND 6 AND e.Weekdays = 1
  • 上述两个 cmets 让我可以“每隔一周”执行一次,并将 dayOfWeek 从每天选择的多条记录中浓缩为每个事件的一条记录。如果其他人有兴趣,我可以发布其余代码,否则您可能可以从上面弄清楚。

标签: c# sql-server date scheduling


【解决方案1】:

我们已经创建了 sql'server 作业,它定期(看着你声称每小时就足够了)调用一些存储过程。另一方面,这个程序选择做两件事:

  1. 根据表 [A] 中的一些递归信息计算 NEXT 用户事件。并将此事件放置到表 [B]
  2. 从表 [B] 中选择准备触发事件

【讨论】:

  • 每小时就可以了,但我认为这并不难,我不需要运行任何东西,而是有办法查看一个日期期间的所有事件,而不仅仅是第一个一。
【解决方案2】:

你可以这样做:

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, 1-@dm, @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 作为默认值(其中星期日 = 1、星期一 = 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

【讨论】:

  • 看起来很酷,前两个似乎也可以。
  • 我认为唯一的问题是如何将事件与实际日期关联起来?假设我有下周的视图,我怎么知道上面的查询要显示哪些天?我认为这会表明下周有活动,但不是特定的日子——至少我认为......
  • 也许您可以使用日历表?让我追加我的答案。
  • 谢谢,我会消化并回复你。
  • 哇,简直太棒了。据我所知,这是可行的,而且您提供的代码非常易于设置和测试。
【解决方案3】:

为了存储日程,看看我在这个问题中的回答

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

这里我将描述 SQL Server 如何将计划信息存储在其sysschedules 和相关表中。他们有一个非常好的架构设计,支持您询问的所有调度案例。 MSDN 上的文档也很有帮助。

要获取 Outlook 类型显示的日期范围之间的所有计划日期,请查看 Peter Larsson 的博客,他创建了一个出色的存储过程来计算这些值。

  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 存储过程。

【讨论】:

  • 再一次,很酷,但是我怎么能看到日期本身的前景呢?比如,我将如何查询以显示未来两周内发生的所有事件。
  • 谢谢,这里有很多信息,让我看看,我会回复你的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-05
  • 2011-03-05
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
相关资源
最近更新 更多