1

ここ数週間、学年ごとに学生をランク付けするというかなり有名な問題に悩まされていました。多くのことを学びましたが、まだ問題を解決していません (ランクは生成されますが、プロセスが遅すぎます)。 :

学生コード(名前の代わりに識別子として機能する)、学生の教室、テスト、テスト日、科目、質問番号、およびその質問に対する学生の成績を含む大きなテーブル(320,000行)があります. このテーブルは、計算される他のすべてのベースであり、そのサイズにより、これらすべての計算が非常に遅くなり、ここで作業しているすべてのものをほとんど壊してしまうほどです。

最初に、学校に関するいくつかの情報 (問題を理解するために必要な情報はほとんどありません)
ここの学校では、いくつかの科目について毎週テストがあります。学校はまた、目的の異なる教室に分かれています (1 つは数学、物理学、化学に重点を置いており、もう 1 つは生物学に重点を置いており、最後の 1 つは歴史、ポルトガル語、地理に重点を置いています)。しかし、全員が毎週同じテストを行っています。

私たちがやりたいことは、学校の全員 (教室ごとではなく) の各質問の標準偏差と、質問ごとの平均成績 (学校の全員) を計算し、次のランクを生成することです (全員が日にち):

-教室ごとの科目ごとのランク (「生」の成績)、学校全体を考慮した科目ごとのランク (「生」の成績)、および学校全体を考慮した科目ごとのランク (正規化された成績を使用、質問ごとの標準偏差と平均)質問情報ごとの成績)
- 上記と同じランクですが、科目ごとではなく、代わりにすべての科目を考慮します

ご覧のとおり、平均成績と標準偏差を計算した後、各問題の成績の合計を計算し、これらの合計 (実際の科目/テストの成績) に従ってランク付けする必要があります。私はいくつかの方法でこの問題を攻撃しました:

1) 2 つのテーブルを作成しました。1 つは科目ごとの生徒ごとの成績です (フィールド: 生徒コード、生徒の教室、テスト日、科目、成績、正規化された成績、教室でのランク、学校でのランク、正規化された成績を使用した学校でのランク) および別のテストごとの生徒ごとの成績 (すべての科目が考慮されます。フィールド: 生徒コード、生徒の教室、テスト日、成績、正規化された成績、教室でのランク、学校でのランク、正規化された成績を使用した学校でのランク)。

これらのテーブルへのデータの挿入には約 50 秒かかります

次に、SQL を使用してランク付けを試みましたが、いくつかの問題に遭遇しまし
た。

SELECT 1+(SELECT Count(*) FROM grades_table_per_subject t2 WHERE 
t2.Grade > t1.Grade AND t1.Date=t2.Date AND t1.Subject=t2.Subject) AS [Global Rank],
1+(SELECT Count(*) FROM grades_table_per_subject t3 WHERE t3.Grade > t1.Grade AND
t3.Date=t1.Date AND t3.Subject=t1.Subject AND t3.Classroom=t1.Classroom) AS
[Rank in classroom] FROM grades_table_per_subject;

上記のクエリには正規化された成績のランクがまだありますが、省略しました。
テーブル grades_table_per_subject には約 45,000 行あり、このクエリは、インデックスを作成しても 15 分以上かかります (多くの異なるインデックスの組み合わせを試してみましたが、機能するはずのものが機能しないことがわかったときに奇妙なものもありました)。
また、内側の選択で ORDER BY Count( ) DESC を試みました
が、7 分後に ctrl+break を押しても結果はありませんでした。

2) 上記の表に次のフィールドを追加しました: 教室でのランク、学校でのランク、正規化された成績を使用した学校でのランク

次に、DAO で VBA を使用して、Rank フィールドを手動で更新し、次のコード (簡易版) を実行してみました。

Set rs = CurrentDb.OpenRecordset("SELECT Classroom, Date, Subject, Grade, [Rank in classroom] FROM
grades_table_per_subject ORDER BY Date, Classroom, Subject, Grade DESC;", dbOpenDynaset)
...
...
rs.movefirst
i=1
While Not rs.eof
 'Verifies if there was a change on either one of Subject, Classroom, Date and if so:
 ...
  i = 1
 ...

 rs.Edit
 rs![Rank in classroom]=i
 rs.Update

 i = i + 1
 rs.movenext
Wend
rs.close

これは明らかにランクの 1 つだけを構築し (この場合は教室ごとの教科ごと)、それだけで 3 分 10 秒かかります。
テーブルへの書き込みのために非常に長い時間がかかることを確認しました (rs.Edit と rs.Update が原因で、それらにコメントすると、すべてがわずか 4 秒で実行されます)、テーブルに書き込まれたランクを生成する必要があります。アクセス報告は後ほど。

最後に:
すべてのランクを 1 回生成して、ユーザーがすべてのデータにすばやくアクセスできるようにすることもできますが、すべてをオンザフライで計算する必要があります。しかし、私たちが達成した時代は、これを不可能にしています。

全体として、尋ねられるべき質問は次のとおりです:
- 10 秒未満で Access Query を介して上記のランクを計算する方法はありますか、または VBA を使用して、サイズを考慮して同様の時間でこれらのランクをテーブルに計算挿入する方法はありますか?ここで使用されているテーブルの

また、効率的なランキングアルゴリズムのリストを見て、すべてをすばやく行うことができなくても、可能な限り改善できるようにしたいと考えています.

4

2 に答える 2

1

すべてのランクを一度生成して、ユーザーがすべてのデータに非常に迅速にアクセスできるようにすることもできますが、すべてをオンザフライで計算する必要があるという考え方です。

なんで?

同じデータを何度も再生成する必要があるのはなぜですか? データが変更されたときにこれらの統計を生成し、1 回おきにそれらを参照することをお勧めします。誰かが何かを確認したいときに、すでに行った作業をやり直すのはばかげています。

于 2010-01-25T20:12:40.290 に答える
0

msアクセスのみと言っているのを見ました

したがって、この回答は無視してください。または、このタイプの電力処理を実行できるようにする場合は、実際の DB への移行を検討してください。

以下の元の回答

テスト データにアクセスできませんが、実行速度はどれくらいですか?

SELECT RANK () OVER (PARTITION BY [Date],[Subject] ORDER BY Grade) AS [Global Rank],
       RANK () OVER (PARTITION BY [Date],[Subject], Classroom ORDER BY Grade) AS [Rank in classroom]
FROM grades_table_per_subject

私の推測では、VBA で SQL Server のランキング速度を超えることはできないと思います。これが十分に高速でない場合は、プロファイラーを調べて、作成するインデックスを確認する必要があります。

于 2010-01-25T20:22:04.863 に答える