Rails order by count based on values of column -


rails 5.1.2

i have 2 models student , award way:

class student < applicationrecord   has_many :awards end  class award < application record   belongs_to :students    # categories   scope :attendance, -> { where(category: 0) }   #...(other award categories)   scope :talent,     -> { where(category: 8) }   # ranks   # gold   scope :rank_1, -> { where(rank: 1) }   # silver   scope :rank_2, -> { where(rank: 2) }   # bronze   scope :rank_3, -> { where(rank: 3) } end 

award has these columns: rank , category.

now, want top student given category. criteria is, order count of "gold" awards (rank 1), order count of "silver" (rank 2) awards, , order count of "bronze" (rank 3) awards.

so, if student meets top criteria category 0 (which handled attendance scope described in model above), thought query should like:

student.joins(:awards).where(awards: { category: 0 }).group('students.id').order('count(awards.rank == 1) desc', 'count(awards.rank == 2) desc', 'count(awards.rank == 3) desc').take 

however, returns student highest count of awards, regardless of rank. example, if remove take, order looks this:

# |st.id | gold  | slvr. | brnz. | ---------------------------------- 1 |  12  |   4   |   12  |   8   | ---------------------------------- 2 |   1  |   9   |   0   |   4   | ---------------------------------- 3 |   6  |   9   |   1   |   0   | ---------------------------------- 4 |  18  |   5   |   2   |   2   | ----------------------------------  ... 

so, order i'm getting ids 12, 1, 6, 18, ..., when should ids 6, 1, 18, 12, ....

i realize order('count(awards.rank == 1) desc', 'count(awards.rank == 2) desc', 'count(awards.rank == 3) desc') part ordering count of awards total (rather count of awards particular value in column rank).

i can solve adding counter cache each category of awards, isn't elegant nor flexible solution.

as bonus, after query returns successful result, search database again find students have same score (as there ties). i'm not aware of way in 1 query (perhaps means of subqueries after getting values each rank).

i think problem might double equal??

edit: more proper way (assuming mysql):

 student.joins(:awards).where(awards: { category: 0 }).group('students.id').order('count(if(awards.rank = 1)) desc', 'count(if(awards.rank = 2)) desc', 'count(if(awards.rank = 3)) desc').take 

first try code without it, if doesn't work, might want try this:

select students.id, gold, silver, bronze) students  join on    (select students.id id count(awards) bronze   students join awards on students.id = awards.student_id   awards.rank = 1   group students.id) q1 q1.id = students.id join on    (select students.id id count(awards) silver   students join awards on students.id = awards.student_id   awards.rank = 2   group students.id) q2 q2.id = students.id join on    (select students.id id count(awards) gold   students join awards on students.id = awards.student_id   awards.rank = 3   group students.id) q3 q3.id = students.id order gold, silver, bronze 

Comments

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -