2013-04-03 50 views
7

我有几个海量的SQL请求涉及到我的rails应用程序中的各种模型的连接。 单个请求可能涉及6到10个表。如何使用ARel加入子查询?

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

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

有没有人有任何想法如何实现这一点(不使用字符串)?

+0

你能显示你正在尝试的查询吗? – mguymon

+0

以便将其简化到极限水平: SELECT A. * INNER JOIN(SELECT B.a_id FROM B WHERE Bc> 4)B ON A.id = B.a_id –

+0

您可以为您尝试的Ruby代码查询? – mguymon

回答

8

皮埃尔,我想到了一个更好的解决方案可能是由以下(从this gist灵感):

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”,我只是认为它不那么令人困惑。

4

好吧,所以我的主要问题是,你不能加入一个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