2009-03-11 7 views
1

Ruby on Railsを使用してデータベース内のフィールドのランクを計算する簡単かつ迅速な方法はありますか?たとえば、私がmath_scoresテーブルを持っていて、与えられたMathScore.find(:all、:condtions => ...:order => ...)を探したい場合、それらのすべてを繰り返してどこを見つけるかテストスコアは下がりますが、もっと簡単な方法が必要です...アドバイスはありますか?Ruby on Railsはデータベースの値に基づいて「ランク」を計算しますか?

ここでスキーマ上のいくつかの情報があります、それだけの単純なテーブルです:

のfirst_nameのVARCHAR(50)

のlast_nameのはvarchar(50)

test_id int型

スコアフロート

明確化: 私は、次のように質問すると、ランクの値をどのように取得するのでしょうか: rank = MathScore.find_by_sql(score_(スコアはhigh_scoresからスコアを選択します。ここで、test_id = 33 AND first_name = 'John' AND last_name = 'Doe')スコア順で順位を選択します(select count * from math_scores )as s ")

クエリに基づいて[#<HighScore:0x6ca4724 @attributes={"rank"=>"3"}>]:Arrayが得られますが、どのようにランク値で取得できますか?事前に

おかげで、 ベン

+0

あなたが持っているスキーマに関するさらに詳しい情報はありますか? このランクはどのように計算されますか? – MatthewFord

答えて

3
sql = "select count(*) as rank from (select * from math_scores where score > (select score from high_scores where test_id = 33 AND first_name = 'John' AND last_name = 'Doe') order by score desc) as s" 
rank = MathScore.find_by_sql(sql)[0].rank 
+0

ありがとう、素晴らしいヒント:) –

2

私は特にRailsのを知らないが、私は、次のSQL例えば、いくつかの同等があると仮定しています。

問題の行の前に来るすべての行のSELECT COUNT(*)+ 1。あなたが項目のスコアを知りませんが、あなたが他の識別情報を知っていれば

SELECT COUNT(*) + 1 as [rank] from my_table 
    WHERE score > 75.0 

スコアあなたが知っている75.0あるアイテムのランクを取得するために例えば

SELECT COUNT(*) + 1 as [rank] from my_table 
    WHERE score > (SELECT score FROM my_table WHERE test_id = 123) 

同じスコアを持つテストに同じランクを割り当てても、それを正しく分散するという副作用があります。したがって、ランク1に1点、ランク2に2点、次にランク4などがあります。この副作用が気に入らない場合は、WHERE句を使って分かち合うことができますtest_idまたは姓と名。

これは一度に1つのテストでのみ適切な解決策です。それらをすべてランク付けしたい場合は、それらをすべてフェッチして、ORDER BYスコアを付けて、ランク付けすることもできます。

0

ベルスコアのどこでテストスコアが下がっているかを調べようとしていますか? STDDEV_POP()のような関数でMySQLの組み込みのグループの1つを使用して、モデルのために独自の関数をローリングすることができます。あなたはそれらを見ることができますhere.派手なフットワークでは、dbへの一回の呼び出しで曲線上の等級の位置を返すことができます。

5

これを助けるために、named scopesをRails 2.2で使用できます。

あなたがコントローラで次の操作を実行できるようになる
class MathScore 
    named_scope :passed, :conditions => {:score => 60..100 } 
    named_scope :failed, :conditions => {:score => 0..59} 
end 

@passing_scores = MathScore.passed 
@failing_scores = MathScore.failed 

ですからビューでそれらを反復処理することができます。 (ERBで)あなたの明確化に対応して


<% your_array.each do |hs| %> 
    <%= hs.rank %> 
<% end %> 
1

あなたが持っているDBMSのかわかりません。ほとんどの場合、rank関数とdense_rank SQL関数(ウィンドウ関数)をサポートしています。例:

SQL> select ename,sal, 
    2 row_number() 
    3  over (order by sal desc)rn, 
    4 rank() 
    5  over (order by sal desc)rnk, 
    6 dense_rank() 
    7  over (order by sal desc)drnk 
    8 from emp 
    9 order by sal desc 
10/

ENAME SAL RN RNK DRNK 
----- ---- -- --- ---- 
KING 5000 1  1  1 
FORD 3000 2  2  2 
SCOTT 3000 3  2  2 
JONES 2975 4  4  3 
BLAKE 2850 5  5  4 
CLARK 2450 6  6  5 
関連する問題