gpt4 book ai didi

mysql - Rails 查询具有关联条件的多个主键

转载 作者:行者123 更新时间:2023-11-29 05:42:54 25 4
gpt4 key购买 nike

在 Active Record 中有没有一种方法可以构造一个查询来对多个主键进行条件连接?

假设我有以下模型:

Class Athlete < ActiveRecord::Base
has_many :workouts
end

Class Workout < ActiveRecord::Base
belongs_to :athlete
named_scope :run, :conditions => {:type => "run"}
named_scope :best, :order => "time", :limit => 1
end

有了它,我可以生成查询以获得运动员的最佳运行时间:

  Athlete.find(1).workouts.run.best

如何使用单个查询获得一组中每位运动员的最佳运行时间?

以下不起作用,因为它只将命名范围应用于整个数组一次,返回所有运动员的单个最佳时间:

Athlete.find([1,2,3]).workouts.run.best

以下作品。但是,它无法针对更多运动员进行扩展,因为它会为每个运动员生成一个单独的查询:

[1,2,3].collect {|id| Athlete.find(id).workouts.run.best}

有没有办法使用 Active Record 查询接口(interface)和关联生成单个查询

如果没有,谁能建议我可以用于 find_by_SQL 的 SQL 查询模式?我必须承认我不是很擅长 SQL,但如果有人能给我指出正确的方向,我可能会弄明白。

最佳答案

获取最佳时间的Workout对象:

athlete_ids = [1,2,3]
# Sanitize the SQL as we need to substitute the bind variable
# this query will give duplicates
join_sql = Workout.send(:santize_sql, [
"JOIN (
SELECT a.athlete_id, max(a.time) time
FROM workouts a
WHERE a.athlete_id IN (?)
GROUP BY a.athlete_id
) b ON b.athlete_id = workouts.athlete_id AND b.time = workouts.time",
athlete_ids])


Workout.all(:joins => join_sql, :conditions => {:athlete_id => })

如果您只需要每个用户的最佳锻炼时间,那么:

Athlete.max("workouts.time", :include => :workouts, :group => "athletes.id", 
:conditions => {:athlete_id => [1,2,3]}))

这将返回一个 OrderedHash

{1 => 300, 2 => 60, 3 => 120}

编辑 1

下面的解决方案避免返回具有相同最佳时间的多个锻炼。如果 athlete_id,此解决方案非常有效和 time列已编入索引。

Workout.all(:joins => "LEFT OUTER JOIN workouts a 
ON workouts.athlete_id = a.athlete_id AND
(workouts.time < b.time OR workouts.id < b.id)",
:conditions => ["workouts.athlete_id = ? AND b.id IS NULL", athlete_ids]
)

阅读此 article了解此查询的工作原理。 workouts.id < b.id 中的最后一次检查 ( JOIN )当最佳时间有多个匹配项时,确保只返回一行。当一个运动员的最佳时间超过一次匹配时,返回具有最高 id 的锻炼(即最后一次锻炼)。

关于mysql - Rails 查询具有关联条件的多个主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5177033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com