【问题标题】:complex join in scope in Rails ActiveRecordRails ActiveRecord 范围内的复杂连接
【发布时间】:2012-04-03 02:34:54
【问题描述】:

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

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

谢谢

【问题讨论】:

    标签: sql activerecord join scope


    【解决方案1】:

    假设用户有很多事件,每个事件都属于一个用户。

    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' AND target_id IN(SELECT DISTINCT id FROM events WHERE (host_id == user.id OR invitee_id == user.id))

    这都是关于 ActiveRecord 关系的,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')
    

    在控制台上试试这个,如果它有效,你可以简单地将其更改为范围。 由于我不确定您要做什么,因此您可能需要进行一些调整。

    【讨论】:

    • 感谢您的回答。我的 user.events 实际上会查找 events.host_id == user.id 或 events.invitee_id == user.id 的事件。有没有 Rails 方法可以做到这一点?
    【解决方案2】:

    这个怎么样?

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

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

    【讨论】:

      猜你喜欢
      • 2018-06-01
      • 2013-04-16
      • 1970-01-01
      • 2011-11-05
      • 2014-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多