10

我有一些大规模的 SQL 请求,涉及跨我的 rails 应用程序中的各种模型进行连接。单个请求可能涉及 6 到 10 个表。

为了更快地运行请求,我想在连接中使用子查询(这样我可以在连接之前过滤这些表并将列减少到我需要的列)。我正在尝试使用 ARel 来实现这一目标。

我以为我在那里找到了解决问题的方法:How to do joins on subqueries in AREL inside Rails,但事情一定已经改变了,因为我得到了undefined method '[]' for Arel::SelectManager.

有谁知道如何实现这一点(不使用字符串)?

4

3 回答 3

9

皮埃尔,我认为更好的解决方案可能如下(灵感来自这个要点):

a = A.arel_table  
b = B.arel_table

subquery = b.project(b[:a_id].as('A_id')).where{c > 4}  
subquery = subquery.as('intm_table')  
query = A.join(subquery).on(subquery[:A_id].eq(a[:id]))

没有特别的理由将别名命名为“intm_table”,我只是认为它不会那么混乱。

于 2013-11-06T14:26:15.433 回答
5

好的,所以我的主要问题是你不能加入 Arel::SelectManager ...但是你可以加入表别名。所以要在我上面的评论中生成请求:

a = A.arel_table
b = B.arel_table

subquery = B.select(:a_id).where{c > 4}
query = A.join(subquery.as('B')).on(b[:a_id].eq(a[:id])
query.to_sql # SELECT A.* INNER JOIN (SELECT B.a_id FROM B WHERE B.c > 4) B ON A.id = B.a_id 
于 2013-04-04T07:42:04.640 回答
0

正在寻找这个,并得到了其他答案的帮助,但两者都有一些错误,例如A.join(...应该是a.join(...
我也错过了如何构建一个ActiveRecord::Relation.

这是ActiveRecord::Relation在 Rails 4 中构建 , 的方法

a = A.arel_table
b = B.arel_table

subsel = B.select(b[:a_id]).where(b[:c].gt('4')).as('sub_select')
joins  = a.join(subsel).on(subsel[:a_id].eq(a[:id])).join_sources
rel    = A.joins(joins)
rel.to_sql
#=> "SELECT `a`.* FROM `a` INNER JOIN (SELECT `b`.`a_id` FROM `b` WHERE (`b`.`c` > 4)) sub_select ON sub_select.`a_id` = `a`.`id`"
于 2020-05-22T08:15:45.113 回答