1

试图学习 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 组合。

对上述数据的查询将产生:

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)

关于如何通过单个连接原始 sql 或活动记录查询接口来完成这一切的任何想法?

4

1 回答 1

0

想出了一个使用 Unions 的解决方案。不幸的是,Rails 关系不支持 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)
于 2013-06-24T04:25:41.980 回答