#ruby-on-rails #ruby-on-rails-3 #activerecord #rails-activerecord
#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
Я хотел бы оставить join Author в области видимости книги «доступным». Ниже приведен запрос, который я хотел бы выполнить в 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
Комментарии:
1. Какой результат вы пытаетесь получить?
2. Чтобы найти количество книг каждого автора (есть авторы и без книг) и упорядочить количество книг.
3. @ShanakaKuruwita То есть вы имеете в виду, что в него должны входить авторы, у которых нет книг, но books_count должен быть равен 0. не так ли?
4. @Vishal точно
Ответ №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")
Комментарии:
1. это кажется хорошим подходом, но это where добавит оператор AND к предложению where вместо not OR. Итак, я в конечном итоге не получаю результатов. метод ‘или’ недоступен в моей версии.
2. @ShanakaKuruwita
or
означает, что метод @ShanakaKuruwita недоступен в вашей версии? вы должны использовать OR в запросе. вы пробовали приведенный выше запрос или внесли изменения в свой существующий запрос?3. да, я попробовал ваш точный запрос. что означало Model.where.или here guides.rubyonrails.org /…
4. @ShanakaKuruwita Но почему вы хотите использовать
or
метод active record, когда вы можете просто использоватьor
с приведенным выше запросом. я думаю, что приведенный выше запрос сработает на 100%. вам не нужно искать какие-либо другие активные методы записи5. Вот запрос, который я получаю:- Выберите authors.* , count(books.*) как books_count От авторов, оставленных для внешнего объединения книг в books.author_id = authors.id где ( books.available = true ) И ( books.author_id РАВНО НУЛЮ ) группируются по (authors.id ) порядок по books_count;
Ответ №2:
Пока оно не использует вашу область видимости. (в основном потому, что ваша область видимости включает предложение 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
Ответ №3:
Если ваше приложение работает на Rails 4.2, то, если вы хотите настоящую поддержку left_outer_joins, просто установите gem «brick», и он автоматически добавит реализацию Rails 5.0 left_outer_joins
. Вы, вероятно, захотите отключить остальную часть его функциональности, если только вы не хотите, чтобы в вашем приложении была доступна автоматическая «панель администратора»!