2013-11-04 37 views
0

我在SQL数据库中有两个表; '课程'和'活动',课程表有courseID(pk),coursecode和coursetitle字段。事件表具有eventID(pk)courseID(fk),startdate,enddate。具有最新日期和下一日期的SQL返回列表

我需要使用事件表的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  | 
+------------+-------------+------------+-------------+------------+-------------+ 

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

我希望我不是在重复一个问题,但到目前为止我还没有发现任何问题。

谢谢大家提前任何帮助

+0

什么是sql的味道? – geomagas

+1

@geomagas 2008 R2 SP2 – laurencemadill

+0

多个'coursecode's也会有''coursecode'多个'coursetitle's。标题选择的标准是什么? – geomagas

回答

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,然后比较它们不是一种有效的方法来删除时间元素。铸造到DATE更有效率(如果你有2008+)。对于其他版本的sql-server中的其他方法,请阅读this article

+0

非常感谢你,这似乎工作,虽然我还没有完全测试它。我乱的日期转换的原因是因为我们的数据库中的日期字段是整数存储为例如'20131104'今天的日期。我对SQL很陌生,所以转换日期字符串可能是我的混乱尝试,所以我可以得到一个日期进行比较。 – laurencemadill

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

如果您不能使用热膨胀系数比你能反而让cteEventsLast和cteEventsNext子查询在FROM子句

我也不会用

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

来比较日期,因为你有你的问题。相反,只需要直接比较日期,即这样

startdate > GETDATE() 
+0

OP特别要求每个'CourseCode'只出现一次。 – geomagas

相关问题