2012-01-31 11 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 

注:あなたはそれを得ることができるなら、これはあなたが探しているクエリがあります。ゼロを主張する場合は、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で、私はそれを動作させることができれば、私は後でAnswerのチェックをクリックするかもしれません。 (私は現在、SQL Server 2012 Expressを持っていません。それは私に関係する唯一のリリース候補です。)また、この構文に慣れていないので、アップグレードする前に質問をしたいと思います。返されないものを含むすべての行の合計を実行させますか? 「さらに(そしてこれは重要です)...」という言葉の段落を参照してください。その注意点が固執ポイントかもしれません。 – PaulOTron2000

+0

SQL Server 2012の起動イベントは、3月7日に予定されています。 SQL Server 2012 Expressの最終的なビットは、その時点で利用可能になるはずです。 http://sqlserverlaunch.com/WW/Homeを参照してください。 –