我在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很好,因为我将在报表设计中对它们进行格式化。
我希望我不会重复一个问题,但到目前为止我还没有找到任何问题。
提前感谢大家提供任何帮助
答案 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()