2013-04-03 7 views
7

Ich habe ein paar massive SQL-Anfrage mit Join über verschiedene Modelle in meiner Rails-Anwendung. Eine einzelne Anfrage kann 6 bis 10 Tabellen umfassen.Wie bei Unterabfragen mit ARel beizutreten?

Um die Anfrage schneller auszuführen, möchte ich Sub-Abfragen in den Joins verwenden (auf diese Weise kann ich diese Tabellen vor dem Join filtern und die Spalten auf diejenigen reduzieren, die ich brauche). Ich versuche das mit ARel zu erreichen.

Ich dachte, ich fand die Lösung für mein Problem dort: How to do joins on subqueries in AREL within Rails, aber Dinge müssen sich geändert haben, weil ich undefined method '[]' for Arel::SelectManager bekomme.

Hat jemand eine Idee, wie man das erreicht (ohne Strings zu verwenden)?

+0

Können Sie die Abfrage anzeigen, die Sie versuchen? – mguymon

+0

Nun, um es auf die extreme Ebene zu vereinfachen: SELECT A. * INNER JOIN (SELECT B.a_id VON B WHERE Bc> 4) B ON A.id = B.a_id –

+0

Können Sie den Ruby-Code, den Sie für die versuchen Abfrage? – mguymon

Antwort

8

Pierre, dachte ich, eine bessere Lösung die folgenden (inspiriert von this gist) sein könnte:

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])) 

kein besonderer Grund für die Benennung des Alias ​​als "intm_table", ich dachte nur, es wäre weniger verwirrend.

4

OK, also war mein Hauptproblem, dass Sie einem Arel :: SelectManager nicht beitreten können ... ABER Sie können einem Tabellenaliasing beitreten. So die Anfrage in meinem Kommentar zu generieren oben:

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