2013-04-03 1 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