连接3个表并检索关联的对象

时间:2013-06-15 04:35:26

标签: ruby-on-rails join

尝试学习rails 3并加入一个辅助项目并遇到了一个我无法理解的联接。这是课程:

class Stuff
  belongs_to :user
  has_many :things
end

class Thing
  belongs_to :user
  belongs_to :stuff
end

class User
  has_many :stuffs
  has_many :things
end

这是样本数据:

Stuff            Thing                     User
id|user_id|data  id|user_id|stuff_id|data  id
--|-------|----  --|-------|--------|----  --
1 |2      |n     1 |1      |nil     |m     1
2 |3      |o     2 |3      |2       |p     2
                 3 |3      |nil     |q     3
                                           4

想要回复:

  1. 所有同时拥有A和B的用户,以获取用户,A,B作为结果, 和
  2. 所有拥有A或B的用户,以获取用户,A或用户,B 组合也是如此。
  3. 对上述数据的查询会产生这样的结果:

    Stuff    Thing        User
    --------------------------
    nil      1|1|nil|m    1
    1|2|n    nil          2
    2|3|o    2|3|2|p      3
             3|3|nil|q    3
    

    可以完成下面的一些内部联接,然后使用ruby删除只有A的用户或只有B的用户与A和B的用户的结果重叠。

    User.includes(:as,:bs).joins(:as, :bs)
    User.includes(:as).joins(:as)
    User.includes(:bs).joins(:bs)
    

    关于如何使用raw sql或active record query interface进行单一连接的所有想法?

1 个答案:

答案 0 :(得分:0)

使用联盟提出解决方案。不幸的是,Rails Relations不支持UNION,但可以使用find_by_sql和paginate_by_sql。下面是实际代码的精简版:

    all = User.paginate_by_sql(
    "SELECT u.id as u_id,
        s.id as s_id,
        cast(null as integer) t_id,
        s.created_at as created_at
    FROM users u
    INNER JOIN stuffs s on s.user_id = u.id where s.thing_id is null
    UNION
    SELECT u.id as u_id,
        cast(null as integer) s_id,
        t.id as t_id
        t.created_at as created_at
    FROM users u
    INNER JOIN things on t.user_id = u.id
    WHERE t.id not in (SELECT things_id FROM s)
    UNION
    SELECT u.id as u_id,
        s.id as s_id,
        t.id as t_id
        s.created_at as created_at
    FROM users u
    INNER JOIN stuffs s on s.user_id = u.id
    INNER JOIN things t on t.user_id = u.id
    ORDER BY created_at", :page => 1, :per_page => 50)