Rails ActiveRecord中的复杂连接范围

时间:2012-04-03 02:34:55

标签: sql activerecord join scope

我有以下范围,我知道这不是最佳范围:

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))

谢谢

2 个答案:

答案 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")
}

它只是重新安排你已经拥有的东西,但是它应该让你只有一个查询,因为它不使用代码中的关联。