ActiveRecord:是否可以与范围建立连接关系

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

这是我原来的问题。我有两个模型如下。

class Author < ActiveRecord::Base
  has_many :books
end

class Book < ActiveRecord::Base
  belongs_to :author

  scope :available, ->{ where(available: true) }
end

我想离开加入作者到Book的范围“可用”。以下是我想在DB上执行的查询。是否有可能做到这一点 ?

Select authors.* , count(books.*) as books_count 
From authors left outer join books on books.author_id = authors.id 
and books.available = true 
group by (authors.id) order by books_count;

我试过以下方法

 Author.joins("LEFT OUTER JOIN authors on books.author_id = authors.id")
.merge(Book.available)
.select("authors.* , count(books.*) as books_count")
.group("authors.id").order("books_count")

但这导致以下查询。

Select authors.* , count(books.*) as books_count 
From authors left outer join books on books.author_id = authors.id 
where books.available = true 
group by (authors.id) order by books_count;

所以它删除了所有没有书的作者。

重要提示:我的AR版本没有left_outer_joins方法

ruby-on-rails ruby-on-rails-3 activerecord rails-activerecord
2个回答
1
投票

您需要再添加一个查询,检查作者是否没有书籍,然后我们需要添加它。请尝试以下查询

 Author.joins("LEFT OUTER JOIN authors on books.author_id = authors.id")
.merge(Book.available)
.where("books.author_id IS NULL")
.select("authors.* , count(books.*) as books_count")
.group("authors.id").order("books_count")

0
投票

虽然它不使用您的范围。 (主要是因为您的范围包含您不希望作为查询一部分的where子句)

您可以使用arel执行此操作,例如:

book_table = Book.arel_table
author_table = Author.arel_table
author_join = author_table.join(book_table,Arel::Nodes::OuterJoin)
  .on(book_table[:author_id].eq(author_table[:id]).and(
       book_table[:available].eq(true)
    )
  )
Author.joins(author_join.join_sources)
  .select("authors.* , count(books.*) as books_count")
  .group("authors.id").order("books_count")

这将导致以下SQL:

SELECT 
  authors.* , 
  count(books.*) as books_count
FROM 
  authors 
  LEFT OUTER JOIN books ON books.author_id = authors.id
    AND books.available = true
GROUP BY 
  authors.id
ORDER BY 
  books_count
© www.soinside.com 2019 - 2024. All rights reserved.