2013-11-04 4 views
0

SQL 데이터베이스에 두 개의 테이블이 있습니다. '코스'와 '이벤트'코스 테이블에는 courseID (pk), coursecode 및 coursetitle 필드가 있습니다. 이벤트 테이블에는 eventID (pk) courseID (fk), startdate, enddate가 있습니다.가장 최근 날짜와 다음 날짜가있는 코스의 SQL 반환 목록

이벤트 테이블의 시작 날짜를 사용하여 일어난 마지막 날짜와 그 다음 날짜를 보여주는 열이있는 모든 강좌 목록을 반환해야합니다. 다음과 같이

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  | 
+------------+-------------+------------+-------------+------------+-------------+ 

나는 각 coursececode를 한 번 보여줄 필요가있다. (코스는 다른 공급자로부터 왔고 따라서 coursecode는 독특한 필드가 아니기 때문에 courseid 필드가 될 수있다.) 과정에 과거 날짜 또는 미래 날짜가 없거나 날짜가 전혀 없을 수도 있습니다. Null은 보고서 디자인에서 서식을 지정하기 때문에 date/eventid 필드에 괜찮습니다.

나는 질문을 반복하지 않기를 바란다. 그러나 나는 지금까지 여기에서 아무 것도 발견하지 못했다. 당신이 사용할 수있는

;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) 

이 예 공통 테이블 표현식을 사용 :

는, 비슷한 시도 사용하는 SQL 어떤 맛에 따라 어떤 도움

+0

SQL의 맛은 무엇입니까? – geomagas

+1

@geomagas 2008 R2 SP2 – laurencemadill

+0

여러 'coursecode'는 'coursecode' 당 여러 개의'coursetitle '을 갖습니다. 제목 선택 기준은 무엇입니까? – geomagas

답변

1

같은 즉, 직접 날짜를 비교이 OUTER APPLY를 사용하여 :

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

StartDate < CAST(GETDATE() AS DATE) 

에 :

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; 

주, 나는이 변경되었습니다

날짜를 varchars로 변환 한 다음이를 비교하는 것이 time 요소를 제거하는 효율적인 방법은 아닙니다. DATE으로 전송하는 것이 훨씬 효율적입니다 (2008+가있는 경우). 다른 버전의 SQL Server의 다른 메소드는 this article입니다.

+0

대단히 감사합니다. 아직 완전히 테스트하지는 않았지만 작동하는 것으로 보입니다. 내 지저분한 날짜 변환의 이유는 데이터베이스의 날짜 필드가 오늘 날짜로 '20131104'와 같이 저장된 정수이기 때문입니다. 나는 SQL에 매우 익숙하다. 그래서 변환 날짜 문자열은 아마도 어질러려는 시도 일 것이므로 비교할 날짜를 얻을 수있을 것이다. – laurencemadill

0

사전에 여러분 모두 감사합니다 TSQL/MSSQL 서버. 절

에서 나는 또한

를 사용하지 않을 당신의 당신이 대신 하위 쿼리로 cteEventsLast 및 cteEventsNext을 할 수있는 것보다하지만 당신의 SQL 맛에 따라 당신은 당신이 열팽창 계수를 사용할 수없는 경우 약간 다른 SQL

을 사용해야 할 수 있습니다

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

귀하의 질문에 감사드립니다. 대신 당신이 달성 할 수있는이

startdate > GETDATE() 
+0

OP는 각 'CourseCode'가 한 번만 나타나도록 특별히 요청했다. – geomagas

관련 문제