我有以下范围,我知道这不是最佳范围:
scope :event_stream_for, lambda{ |user|
where("target_id in (?) and target_type = ?", user.events.collect(&:id), "Event")
}
这会创建3个查询。我该如何优化呢?
或者,如何将整个sql语句放在范围的lambda中,如
SELECT * FROM activities WHERE target_type =='Event' AND target_id IN (SELECT DISTINCT id FROM events WHERE (host_id == user.id OR invitee_id == user.id))
谢谢
答案 0 :(得分:4)
假设用户有很多事件,每个事件都属于一个用户。
scope :event_stream_for, lambda{ |user
joins(:events). # or joins("LEFT JOIN events ON events.user_id = users.id").
where(["target_type=?", "Event"])
}
这将运行一个查询。没有用你的表测试我的代码,但它的工作方式应该类似。
-----------------------根据您编辑的问题-------------------
SELECT * FROM活动WHERE target_type =='Event'和target_id IN(SELECT DISTINCT id FROM events WHERE(host_id == user.id OR inviteee_id == user.id))
所有关于ActiveRecord Relation,http://railscasts.com/episodes/239-activerecord-relation-walkthrough?view=asciicast
Activity.
select("*,distinct events.id AS events_id").
joins("events ON (events.host_id = #{user.id} OR events.invitee_id = #{user.id}").
where(:target_type => 'Event')
在控制台上尝试此操作,如果它可以工作,您只需将其更改为范围即可。 由于我不确定你要做什么,你可能需要进行一些调整。
答案 1 :(得分:1)
这个怎么样?
scope :event_stream_for, lambda{ |user|
where("target_id in (SELECT DISTINCT id FROM events WHERE (host_id == ? OR invitee_id == ?) and target_type = ?", user.id, user.id, "Event")
}
它只是重新安排你已经拥有的东西,但是它应该让你只有一个查询,因为它不使用代码中的关联。