ActiveRecord:是否可以与范围进行联接关系

时间:2019-03-10 23:01:58

标签: ruby-on-rails ruby-on-rails-3 activerecord rails-activerecord

这是我最初的问题。我有以下两种型号。

class Author < ActiveRecord::Base
  has_many :books
end

class Book < ActiveRecord::Base
  belongs_to :author

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

我想让Author加入Book的范围“可用”。以下是我想在数据库上执行的查询。可以这样做吗?

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方法

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分: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