2012-01-31 36 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。也就是說,只有在PRIOR日期的課程中,同一個學生的所有課程的所有分鐘的總和。

所以查詢將返回:

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 2012-01-31 06:18:16

+0

我還沒有檢查過,但請注意,當你輸入你的答案時,我完全重寫了我的問題。對於那個很抱歉。 – PaulOTron2000 2012-01-31 06:18:51

+0

好吧,我已經檢查過了。當然,它有點像我最初編寫的問題,它有加入,而不是上面顯示的內容。 (我可以處理連接問題。)它包含GetDate,它與當前日期無關,因爲每個課程都有其自己的日期字段,因此無論執行何時,相同的查詢都會產生相同的結果。謝謝你。 – PaulOTron2000 2012-01-31 06:26:29

1

這是使用窗聚集的大好機會。訣竅是你需要SQL Server Express。如果你能得到它,那麼這就是你要找的查詢:

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

注意,它返回空值,而不是0(零)。如果你堅持零,使用COALESCE函數將NULL變成零。

我建議使用一個嵌套查詢限制行數返回:

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,如果我能使它工作,我可以稍後點擊檢查答案。 (我目前沒有SQL Server 2012 Express,它只是一個關注我的候選版本。)另外,我對此語法不熟悉,因此在升級之前,我想問一個問題:「未綁定的前導」導致它執行所有行的總和,包括那些不被返回的行?看到我的段落開頭:「此外,(這很重要)......」這個警告可能是一個棘手的問題。 – PaulOTron2000 2012-02-01 05:45:18

+0

針對SQL Server 2012的啓動事件定於3月7日舉行。 SQL Server 2012 Express的最終位應該在當時可用。請參閱http://sqlserverlaunch.com/WW/Home。 – 2012-02-02 04:04:39