2013-04-03 14 views
7

Mam kilka ogromnych żądań SQL dotyczących łączenia różnych modeli w mojej aplikacji rails. Pojedyncze żądanie może obejmować od 6 do 10 tabel.Jak dołączyć do podzapytań za pomocą AREL?

Aby szybciej uruchomić żądanie, chcę użyć pod zapytań w łączeniach (w ten sposób mogę filtrować te tabele przed połączeniem i zmniejszać kolumny do tych, których potrzebuję). Próbuję to osiągnąć za pomocą ARel.

Pomyślałem, że znalazłem rozwiązanie mojego problemu: How to do joins on subqueries in AREL within Rails, , ale rzeczy musiały się zmienić, ponieważ otrzymałem undefined method '[]' for Arel::SelectManager.

Czy ktoś ma pomysł, jak to osiągnąć (bez użycia ciągów)?

+0

Czy możesz pokazać zapytanie, które próbujesz? – mguymon

+0

Cóż, aby uprościć go do ekstremalnego poziomu: WYBIERZ A. * WEJŚCIE WEWNĘTRZNE (WYBIERZ B.a_id OD B GDZIE Bc> 4) B WŁĄCZ A.id = B.a_id –

+0

Czy możesz podać kod Ruby, którego próbujesz użyć? pytanie? – mguymon

Odpowiedz

8

Pierre, myślałem, że lepszym rozwiązaniem może być następująca (inspiracja z 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])) 

Nie szczególny powód do nazywania alias jako "intm_table", po prostu pomyślałem, że będzie mniej dezorientujący.

4

OK, więc moim głównym problemem było to, że nie możesz dołączyć do Arel :: SelectManager ... ALE możesz dołączyć do aliasowania tabeli. Tak, aby wygenerować żądanie w moim komentarzu powyżej:

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