与ORDER结合使用时DISTINCT的问题

我正在尝试建立一个网站,为特定事件中的一些运动员排名表现 – 我之前发布了一个问题,收到了一些好的回答,我现在可以确定我的代码的关键问题。

我有2个模型 – AthleteResult (运动员有很多结果)

每个运动员都可以记录特定赛事的一些时间,我想确定每个运动员最快的时间,并在所有运动员中排列这些最快的时间。

我使用以下代码:

   params[:justevent]).joins(:athlete).order('performance_time_hours ASC').order('performance_time_mins ASC').order('performance_time_secs ASC').order('performance_time_msecs ASC') %> 

这成功地对所有运动员的所有结果进行排序(即一名运动员可以根据他们记录的时间在不同的地方出现多次)。

我现在希望为每位运动员取出最佳成绩,并将其纳入排名。 我可以使用以下方法选择与最佳结果相对应的时间:

   params[:justevent]).where(:athlete_id => filtered_name.athlete_id).order('performance_time_hours ASC').order('performance_time_mins ASC').order('performance_time_secs ASC').order('performance_time_msecs ASC').first() %> 

但是,当我尝试识别@filtered_names列出的不同运动员名字时,我的问题出现了。 我尝试使用但这并不像我预期的那样,有时它会以错误的顺序排名。

我发现,因为它代表我的代码基本上寻找不同的运动员结果之间的差异,从小时时间开始到进展到分钟,秒和毫秒。 一旦发现每个不同运动员的结果之间存在差异,它就会相应地命令它们。

例如,如果我有2名运动员:

 Time for Athlete 1 = 0:0:10:5 Time for Athlete 2 = 0:0:10:3 

这将产生命令,运动员2,运动员1

但是,如果我有:

 Time for Athlete 1 = 0:0:10:5 Time for Athlete 2 = 0:0:10:3 Time for Athlete 2 = 0:1:11:5 

然后命令为运动员1,运动员2,因为第一个差异是在分钟数字,运动员2是慢…

任何人都可以建议一种解决这个问题的方法,并且基本上记下@filtered_names的条目,在第一次出现时拉出每个名称(即保持名称按照它们首次出现在@filtered_names中的顺序

谢谢你的时间

如果您使用的是Ruby 1.9.2+,则可以使用Array#uniq #uniq并传递一个指定如何确定唯一性的块。 例如:

 @unique_results = @filtered_names.uniq { |result| result.athlete_id } 

这应该只返回每个运动员一个结果,并且一个结果应该是数组中的第一个,这反过来将是您已经订购结果的最快时间。

一个警告: @filtered_names可能仍然是一个ActiveRecord::Relation ,它有自己的#uniq方法。 您可能首先需要调用#all来返回结果数组:

 @unique_results = @filtered_names.all.uniq { ... } 

您应该使用DB来执行最大计算,而不是ruby代码。 在results表中添加一个名为total_time_in_msecs的新列,并在每次更改“结果”表时total_time_in_msecs设置值。

 class Result < ActiveRecord::Base before_save :init_data def init_data self.total_time_in_msecs = performance_time_hours * MSEC_IN_HOUR + performance_time_mins * MSEC_IN_MIN + performance_time_secs * MSEC_IN_SEC + performance_time_msecs end MSEC_IN_SEC = 1000 MSEC_IN_MIN = 60 * MSEC_IN_SEC MSEC_IN_HOUR = 60 * MSEC_IN_MIN end 

现在,您可以按如下方式编写查询:

 athletes = Athlete.joins(:results). select("athletes.id,athletes.name,max(results.total_time_in_msecs) best_time"). where("results.event_name = ?", params[:justevent]) group("athletes.id, athletes.name"). orde("best_time DESC") athletes.first.best_time # prints a number 

写一个简单的帮手来分解数字时间部分:

 def human_time time_in_msecs "%d:%02d:%02d:%03d" % [Result::MSEC_IN_HOUR, Result::MSEC_IN_MIN, Result::MSEC_IN_SEC, 1 ].map do |interval| r = time_in_msecs/interval time_in_msecs = time_in_msecs % interval r end end 

在视图中使用帮助程序显示细分时间。