Как сделать соединения по подзапросам в AREL в Rails - PullRequest
10 голосов
/ 23 сентября 2011

У меня есть простая модель

class User
    has_many :logs


class Logs

, связанная обычным способом через внешний ключ logs.user_id.Я пытаюсь сделать следующее, используя Arel, и в соответствии с документом Arel это должно работать.

u_t = Arel::Table::new :users
l_t = Arel::Table::new :logs

counts = l_t.
    group(l_t[:user_id]).
    project(
        l_t[:user_id].as("user_id"),
        l_t[:user_id].count.as("count_all")
    )

l_t.joins(counts).on(l_t[:id].eq(counts[:user_id]))

Когда я это делаю, я получаю ошибку

TypeError: Cannot visit Arel::SelectManager

Однако авторArel явно предлагает , что Arel может делать подобные вещи.

Пожалуйста, не пишите ответы о том, как я могу выполнить тот же запрос с помощью raw SQL, другого типа запроса Arel и т. Д.шаблон, который меня интересует, а не конкретные результаты этого запроса.

Ответы [ 2 ]

8 голосов
/ 01 марта 2012

Вы можете использовать join_sources для получения Arel :: Nodes :: Join из экземпляра Arel :: SelectManager и передачи его в объединения

Используя ваш пример:

l_t.joins(counts.join_sources).on(l_t[:id].eq(counts[:user_id]))
0 голосов
/ 14 февраля 2019

Это позволяет объединить вложенный подзапрос select с Arel:

Вы можете добавить вложенный inner_query и external_query в файл модели и использовать ...

  inner_query = Model.inner_query(params)
  result = Model.outer_query(params).joins(Arel.sql("(#{inner_query.to_sql})"))
   .group("...")
   .order("...")

Для вариантовдля этого, например, чтобы использовать INNER JOIN в подзапросе, выполните следующие действия:

  inner_query = Model.inner_query(params)
  result = Model.outer_query(params).joins(Arel.sql("INNER JOIN (#{inner_query.to_sql}) tablealias ON a.id = b.id"))
   .group("...")
   .order("...")

Добавьте в конкретные объединения, ограничения и группировки к каждой из областей запросов для дальнейшего изменения оператора sql, т. е.

scope :inner_query , -> (company_id, name) {
    select("...")
    .joins("left join table1 on table1.id = table2.id")
    .where("table1.company_id = ? and table1.name in (?)", company_id, name)
    .group("...")
}

Это позволяет вам ставить условия WHERE для вложенного запроса, а также для внешнего запроса

...