SQL返回最近日期和下一个日期的课程列表

时间:2013-11-04 10:52:22

标签: sql date join sql-server-2008-r2

我在SQL数据库中有两个表; 'course'和'event',课程表有courseID(pk),coursecode和coursetitle字段。事件表具有eventID(pk)courseID(fk),startdate,enddate。

我需要使用事件表的startdate返回所有课程的列表,其中列显示最后发生的日期,以及下一个日期。

我可以在事件表中获取最新日期或特定课程的下一个日期,如下所示:

SELECT TOP 1
    startdate as nextdate    
FROM event

WHERE 
    CONVERT(VARCHAR(8),startdate,112) > CONVERT(VARCHAR(8), GETDATE(), 112)
    AND coursecode = 'acc01'

ORDER BY startdate ASC

我希望结果显示如下:

+------------+-------------+------------+-------------+------------+-------------+
| coursecode | coursetitle | lastevent  | lasteventid | nextevent  | nexteventid |
+------------+-------------+------------+-------------+------------+-------------+
| acc01      | Access      | 2012-09-30 | 20127       | 2013-12-10 | 35612       | 
| wrd37      | Word        | 2013-11-02 | 34816       | NULL       | NULL        |
+------------+-------------+------------+-------------+------------+-------------+

我需要一次显示每个课程代码(课程来自不同的供应商,因此课程代码可能不是一个独特的领域,因此是courseid字段)。该课程可能没有过去日期,未来日期或任何日期。在这些日期/偶数字段中,Null很好,因为我将在报表设计中对它们进行格式化。

我希望我不会重复一个问题,但到目前为止我还没有找到任何问题。

提前感谢大家提供任何帮助

2 个答案:

答案 0 :(得分:1)

您可以使用OUTER APPLY

实现此目的
WITH CourseCodeEvents AS
(   SELECT  c.CourseCode, e.EventID, e.StartDate, e.EndDate
    FROM    Course c
            INNER JOIN Event e
                ON e.CourseID = c.CourseID
), DistinctCourseCode AS
(   SELECT  DISTINCT CourseCode, CourseTitle
    FROM    Course
)
SELECT  c.CourseCode,
        c.CourseTitle,
        LastEvent = LastEvent.StartDate,
        LastEventID = LastEvent.EventID,
        NextEvent = NextEvent.StartDate,
        NextEventID = NextEvent.EventID
FROM    DistinctCourseCode c
        OUTER APPLY
        (   SELECT  TOP 1 EventID, StartDate, EndDate
            FROM    CourseCodeEvents e
            WHERE   e.CourseCode = c.CourseCode
            AND     e.StartDate > CAST(GETDATE() AS DATE)
            ORDER BY StartDate ASC
        ) NextEvent
        OUTER APPLY
        (   SELECT  TOP 1 EventID, StartDate, EndDate
            FROM    CourseCodeEvents e
            WHERE   e.CourseCode = c.CourseCode
            AND     e.StartDate <= CAST(GETDATE() AS DATE)
            ORDER BY StartDate DESC
        ) LastEvent;

注意,我也改变了这个:

CONVERT(VARCHAR(8),startdate,112) > CONVERT(VARCHAR(8), GETDATE(), 112)

StartDate < CAST(GETDATE() AS DATE)

将日期转换为varchars然后比较它们不是删除time元素的有效方法。投射到DATE效率更高(如果你有2008+)。对于其他版本的sql-server中的其他方法,请阅读this article

答案 1 :(得分:0)

根据您使用的sql风格,尝试类似于:

的内容
;WITH cteEventsLast
AS
(
    SELECT e.CourseID, 
           MAX(e.StartDate) AS StartDate
    FROM Event e
    WHERE e.StartDate < GETDATE()
    GROUP BY e.CourseID
),

WITH cteEventsNext
AS
(
    SELECT e.CourseID, 
           MIN(e.StartDate) AS StartDate
    FROM Event e
    WHERE e.StartDate >= GETDATE()
    GROUP BY e.CourseID
)

SELECT c.CourseCode,
       c.CourseTitle,
       el.StartDate AS LastEvent,
       en.StartDate AS NextEvent
FROM Course c LEFT OUTER JOIN
     cteEventsLast el ON (el.CourseID = c.CourseID) LEFT OUTER JOIN
     cteEventsNext en ON (en.CourseID = c.CourseID)

此示例使用公用表表达式,您可以将其用于TSQL / MSSQL服务器。但是根据您的SQL风格,您可能需要使用稍微不同的SQL

如果您不能使用CTE而不是将cteEventsLast和cteEventsNext作为FROM子句中的子查询

我也不会用

CONVERT(VARCHAR(8),startdate,112) > CONVERT(VARCHAR(8), GETDATE(), 112)

比较日期,就像你的问题一样。而只是直接比较日期,即像这样

startdate > GETDATE()