2012-01-31 5 views
2

간단하게하기 위해 제 질문을 완전히 다시 작성하고 있습니다. 죄송합니다 이전 버전을 읽으면. (이 질문의 이전 버전은 내가 필요로하는 것과 혼란스럽게 만든 매우 복잡한 쿼리 예제를 포함하고 있습니다.) SQL Express를 사용하고 있습니다.실행중인 Tally에 대해 SQL Sum 및 Group By?

나는 수업 목록이 있습니다.

LessonID StudentID StudentName LengthInMinutes 
1   1   Chuck  120 
2   2   George  60 
3   2   George  30 
4   1   Chuck  60 
5   1   Chuck  10 

날짜별로 정렬됩니다. (물론 실제 테이블은 날짜와 다른 레슨 관련 데이터가 포함 된 수천 개의 레코드입니다. 그러나 이것은 단순화 된 것입니다.)

이 테이블을 쿼리하여 모든 행을 가져 오거나 날짜별로 행의 하위 집합을 가져와야합니다. 범위 또는 학생)하지만, 우리는 PriorLessonMinutes라고 부를 수있는 새로운 열을 추가하기 위해 쿼리를 필요로합니다. 즉, 이전 수업의 동일한 학생에 대한 모든 수업의 모든 분을 합한 것입니다.

그래서 쿼리가 반환 :

LessonID StudentID StudentName LengthInMinutes PriorLessonMinutes 
1   1   Chuck  120    0 
2   2   George  60    0 
3   2   George  30    60 (The sum Length from row 2 only) 
4   1   Chuck  60    120 (The sum Length from row 1 only) 
5   1   Chuck  10    180 (The sum of Length from rows 1 and 4) 

은 본질적으로, 나는 각 학생에 대한 사전 수업 분의 합계의 실행 집계가 필요합니다. 이상적으로 집계에는 현재 행이 포함되어서는 안되지만, 그렇다면 쿼리를받는 코드에서 뺄셈을 수행 할 수 있으므로 큰 문제는 아닙니다.

레코드의 하위 집합 만 검색하는 경우 (예 : 날짜 범위에 따라) PriorLessonMinutes는 반환되지 않는 행을 고려한 합계 여야합니다.

첫 번째 아이디어는 SUM()과 GROUP BY Student에 사용하는 것이지만 잘못된 것이 아니라면 이후에 나오는 행을 포함하여 각 학생의 모든 행에 대한 분 합계가 포함되기 때문에 올바르지 않습니다. 내가 필요한 금액과 관련이없는 행.

옵션 거부 : 코드를받는 모든 행을 스캔 할 수 있지만 (필자가 모든 행을 불필요하게 검색 할 수는 있지만) 분명히 비효율적입니다. 실제 데이터 필드를 거기에 넣고 채울 수도 있지만, 이것 역시 다른 레코드가 삭제되거나 변경 될 때 문제가됩니다.

이러한 쿼리를 함께 작성하는 방법을 알지 못합니다. 어떤 지침?

답변

0

나는 다음과 같은 코드가 purpose.Check을 될 것입니다 느낌 : -

select Students.StudentID ,Students.First, Students.Last,sum(Lessons.LengthInMinutes)  
    as TotalPriorMinutes from lessons,students 
    where Lessons.StartDateTime < getdate() 
    and Lessons.StudentID = Students.StudentID 
    and StartDateTime >= '20090130 00:00:00' and StartDateTime < '20790101 00:00:00' 
    group by Students.StudentID ,Students.First, Students.Last 
+0

내 코드를 확인 했습니까? – Sukanya

+0

아직 확인하지 않았지만 답변을 입력하는 동안 완전히 질문을 다시 작성했습니다. 미안합니다. – PaulOTron2000

+0

글쎄, 지금 확인해 봤어. 물론 그것은 다소 원래 위에 쓰여진 나의 질문을 언급하고 있습니다. (저는 조인 문제를 처리 할 수 ​​있습니다.) 그리고 각 레슨마다 고유 한 날짜 필드가 있으므로 현재 날짜 인 GetDate가 포함되어 있으므로 동일한 쿼리가 실행될 때와 관계없이 동일한 결과가 나타납니다. 그래도 감사합니다. – PaulOTron2000

1

이 윈도우 된 골재를 사용할 수있는 좋은 기회입니다. 트릭은 SQL Server Express가 필요하다는 것입니다. 대신 0 (제로)의 널 (null)을 반환

select *, 
    sum(LengthInMinutes) 
    over (partition by StudentId order by LessonId 
     rows between unbounded preceding and 1 preceding) 
    as PriorLessonMinutes 
from Lessons 

참고 : 당신이 그것을 얻을 수 있다면, 다음이 당신이 찾고있는 쿼리입니다. 0을 고집하는 경우 COALESCE 함수를 사용하여 NULL을 0으로 만듭니다. 내가 행의 수를 제한하는 중첩 된 쿼리를 사용하는 것이 좋습니다

반환 : 필터가 집계 한 후 적용

select * from 
(
    select *, 
    sum(LengthInMinutes) 
     over (partition by StudentId order by LessonId 
     rows between unbounded preceding and 1 preceding) 
     as PriorLessonMinutes 
    from Lessons 
) as NestedLessons 
where LessonId > 3 -- this is an example of a filter 

이 방법이 완료됩니다.

이제는 특정 학생의 데이터 만 쿼리하는 것과 같이 집계에 영향을주지 않는 필터를 적용하려면 영향을주지 않는 행을 정리하는 것으로 내부 쿼리에 필터를 적용해야합니다 일찍 계산 (다른 학생들을위한 데이터와 같이)하면 성능이 향상됩니다.

+0

매우 흥미 롭습니다. 지금까지 그것은 upvote이고, 나는 그것이 작동하게 할 수 있다면 Answer를위한 체크를 나중에 클릭 할 것입니다. (저는 현재 SQL Server 2012 Express를 가지고 있지 않습니다. 그것은 저에게 우려되는 릴리스 후보입니다.) 또한이 구문에 익숙하지 않아서 업그레이드하기 전에 질문을하고 싶습니다. "언 바운드 선행" 반환되지 않은 행을 포함하여 모든 행의 합계를 수행합니까? 다음과 같이 시작하는 내 단락을보십시오 : "더 나아가 (그리고 이것은 중요합니다) ..."그 경고는 고집이 될 수 있습니다. – PaulOTron2000

+0

SQL Server 2012의 출시 이벤트는 3 월 7 일로 예정되어 있습니다. SQL Server 2012 Express의 마지막 비트는 그 시간대에 제공되어야합니다. http://sqlserverlaunch.com/WW/Home을 참조하십시오. –