如何在Rails中的AREL中的子查询上进行连接

问题描述 投票:10回答:2

我有一个简单的模型

class User
    has_many :logs


class Logs

通过外键logs.user_id以通常的方式相关。我正在尝试使用Arel执行以下操作,并且根据Arel doc它应该可以工作。

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 explicitly suggests的作者Arel可以做这种事情。

请不要写关于如何使用原始sql,另一种类型的Arel查询等实现相同查询的响应。这是我感兴趣的模式,而不是此查询的特定结果。

ruby-on-rails-3.1 inner-join arel
2个回答
8
投票

您可以使用join_sources从Arel :: SelectManager的实例中检索Arel :: Nodes :: Join,并将其传递给连接

使用你的例子:

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

0
投票

这实现了嵌套的select子查询与Arel的连接:

您可以在模型文件中添加嵌套的inner_query和outer_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条件放在嵌套查询以及外部查询上

© www.soinside.com 2019 - 2024. All rights reserved.