2009-03-11 4 views
1

Gibt es eine einfache und schnelle Möglichkeit, den Rang eines Feldes in einer Datenbank mit Ruby on Rails zu berechnen? Wenn ich zum Beispiel eine math_scores-Tabelle habe und eine MathScore.find (: all,: condtions => ...: order => ...) finden möchte, dann iteriere sie alle, um herauszufinden, wo das Testergebnis fällt, aber es muss einen einfacheren Weg geben ... Irgendeinen Rat?Ruby on Rails berechnet "Rang" basierend auf Datenbankwerten?

Hier einige Informationen über das Schema, es ist nur eine einfache Tabelle:

first_name varchar (50)

last_name varchar (50)

test_id int

Partitur float

Klarstellung: Ich denke, durch Frage ist näher, wie würde ich den Rang Wert abrufen, wenn Sie tun: rank = MathScore.find_by_sql ("whlen Sie count (*) als Rang aus (whlen Sie * aus math_scores where score> (whlen Sie aus high_scores where test_id = 33 AND first_name = 'John' UND last_name = 'Doe') order by score desc) wie s ")

Ich bekomme [#<HighScore:0x6ca4724 @attributes={"rank"=>"3"}>]:Array basierend auf der Abfrage, aber wie komme ich auf den Rang Wert?

Vielen Dank im Voraus, Ben

+0

Können wir weitere Informationen über das Schema erhalten, das Sie haben? Und wie wird dieser Rang berechnet? – MatthewFord

Antwort

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

Danke, großer Tipp :) –

2

Ich weiß nicht besonders Rails, aber ich gehe davon aus, dass eine Entsprechung für die folgende SQL-Beispiel.

SELECT COUNT (*) + 1 aller Zeilen, die vor der betreffenden Zeile stehen würden.

Zum Beispiel den Rang eines Artikels zu erhalten, deren Punktzahl Sie wissen, ist 75,0:

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

Wenn Sie die Partitur der Artikel nicht kennen, aber man weiß ja andere identifizierende Informationen:

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

Dies hat den Nebeneffekt, dass Tests, die dieselbe Punktzahl haben, denselben Rang erhalten, aber immer noch richtig verteilt werden. Sie könnten also eine Punktzahl auf Rang 1 haben, dann zwei Punktzahlen für Rang 2, dann würde die nächste Rang 4 usw. haben. Wenn Sie diesen Nebeneffekt nicht mögen, können Sie sich mit Ihrer WHERE-Klausel aufteilen, um sie zu teilen test_id oder Vor- und Nachname.

Dies ist nur eine geeignete Lösung für jeweils einen Test. Wenn Sie sie alle ordnen wollen, können Sie sie alle, ORDER BY, holen und sie selbst einstufen.

0

Versuchen Sie zu bestimmen, wo in der Glockenkurve ein Testergebnis liegt? Sie könnten versuchen, eine eigene Funktion für das Modell zu erstellen, indem Sie eine der von MySQL integrierten Funktionen wie STDDEV_POP() verwenden. Sie können sie sehen here. Mit etwas schicker Beinarbeit können Sie die Position der Note auf der Kurve mit einem Anruf zur db zurückgeben.

5

Sie können named scopes mit Rails 2.2 verwenden, um damit zu helfen, z.

class MathScore 
    named_scope :passed, :conditions => {:score => 60..100 } 
    named_scope :failed, :conditions => {:score => 0..59} 
end 

die es erlauben würden Sie die folgenden in einem Controller zu tun:

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

So kann man durch sie in einer Ansicht laufen.


Als Antwort auf Ihre Klarstellung (in erb):

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

nicht sicher, was DBMS Sie haben; aber die meisten unterstützen Rang und Dichte_Rank SQL-Funktionen (Fensterfunktionen). Beispiel:

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