如何在SQL表中创建一系列特定日期?

时间:2013-05-21 19:49:33

标签: sql

我有一个名为CLASSTIMES的表,它有一个bool类型的列,用于一周中的每一天(SUNDAY,MONDAY,TUESDAY ......等),还包含一个STARTDATE和ENDDATE列。例如,我有一行选择MONDAY和WEDNESDAY,其2013年6月3日的STARTDATE和2013年6月26日的ENDDATE。

我希望能够做的是创建一个SPROC,将一系列行插入一个名为CLASSCALENDAR的表中,该表包含每个选定日期列的StartDate和EndDate之间的所有日期。

例如,如果用户从ClassTimes表中选择了Monday和Wednesay,它将生成:

Row    Date
1      2013-06-03
2      2013-06-10
3      2013-06-17
4      2013-06-24
5      2013-06-05
6      2013-06-12
7      2013-06-19
8      2013-06-26

我试图设置它,但它有点超过我的头脑。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

这是一个可能适合您的SQL语句。

SELECT course,
       Convert(varchar(25), course_date, 101) AS course_date
  FROM (SELECT course_no AS course,
               DATEADD(dd, rn-1, startdate) AS course_date,
               DATENAME(dw, DATEADD(dd, rn-1, startdate)) AS dow
          FROM (SELECT row_number() OVER (ORDER BY c1) AS rn
                  FROM dummy) sub1,
               classtimes
         WHERE rn <= (DATEDIFF(dd, startdate, enddate)+1)
       ) list_of_dates,
       (SELECT course_no,
               (CASE monday WHEN 1 THEN 'Monday' END) AS dow
          FROM classtimes
        UNION
        SELECT course_no,
               (CASE tuesday WHEN 1 THEN 'Tuesday' END)
          FROM classtimes
        UNION
        SELECT course_no,
               (CASE wednesday WHEN 1 THEN 'Wednesday' END)          
          FROM classtimes
        UNION
        SELECT course_no,
               (CASE thursday WHEN 1 THEN 'Thursday' END)
          FROM classtimes
        UNION
        SELECT course_no,
               (CASE friday WHEN 1 THEN 'Friday' END)
          FROM classtimes
        UNION
        SELECT course_no,
               (CASE saturday WHEN 1 THEN 'Saturday' END)
          FROM classtimes
        UNION
        SELECT course_no,
               (CASE sunday WHEN 1 THEN 'Sunday' END)
          FROM classtimes
        ) class_days
 WHERE list_of_dates.dow = class_days.dow
   AND list_of_dates.course = class_days.course_no
 ORDER BY course_no,
          course_date

我使用了查询

SELECT course_no AS course,
       DATEADD(dd, rn-1, startdate) AS course_date,
       DATENAME(dw, DATEADD(dd, rn-1, startdate)) AS dow
  FROM (SELECT row_number() OVER (ORDER BY c1) AS rn
          FROM dummy) sub1,
       classtimes
 WHERE rn <= (DATEDIFF(dd, startdate, enddate)+1)

生成每个课程的startdate和enddate之间所有日期的列表。为了使此查询正常工作,虚拟表必须至少包含与每个课程的startdate和enddate之间的天数一样多的行。因此,结果是每个课程的开始日期和结束日期之间的天数列表,以及该日期的星期几。

| COURSE | COURSE_DATE |       DOW |
------------------------------------
|   MATH |  06/03/2013 |    Monday |
|   MATH |  06/04/2013 |   Tuesday |
|   MATH |  06/05/2013 | Wednesday |
|   MATH |  06/06/2013 |  Thursday |
|   MATH |  06/07/2013 |    Friday |
.........
.........
|   MATH |  06/24/2013 |    Monday |
|   MATH |  06/25/2013 |   Tuesday |
|   MATH |  06/26/2013 | Wednesday |

然后我有一个子查询,它使用一系列UNION来从classtimes表中获取星期几列,并生成一周中要保留类的日期。然后,我将list_of_dates子查询与class_days子查询一起加入,以获取类的日期。

|  COURSE | COURSE_DATE |
-------------------------
|    MATH |  06/03/2013 |
|    MATH |  06/05/2013 |
|    MATH |  06/10/2013 |
|    MATH |  06/12/2013 |
|    MATH |  06/17/2013 |
|    MATH |  06/19/2013 |
|    MATH |  06/24/2013 |
|    MATH |  06/26/2013 |

我确信从classtimes表(class_days子查询)生成类的星期几列表有更高效/更优雅的方法,但我想不出一个。