Подсчет записей после предложения where - PullRequest
0 голосов
/ 13 июня 2018

У меня есть три модели: Catalog, Upload и Product.Продукт принадлежит каталогу, а загрузка принадлежит продукту.

Мне нужно посчитать количество загрузок для всех продуктов данного каталога.

Так я и делал до сих пор, что невероятно медленно для большого количества загрузок или продуктов:

@products = Product.where(catalog_id: 123)
@uploads_count = Upload.where(product_id: @products.pluck(:id)).count

Я бы хотел не загружать всепродукты только для подсчета.Должен ли я использовать сырой SQL или есть лучший способ сделать это с ActiveRecord?

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Другой способ избежать выбора записей - использовать подзапрос.Это можно сделать следующим образом:

query = User.where(id: 1..100)
User.where(id: query.select(:id)).count
# [DEBUG]  (10.5ms)  SELECT COUNT(*) FROM "users" WHERE "users"."id" IN (SELECT "users"."id" FROM "users" WHERE ("users"."id" BETWEEN $1 AND $2))  [["id", 1], ["id", 100]]
# => 33

Итак, User.where(id: 1..100) подготавливает запрос, который можно использовать в качестве дополнительного выбора..select(:field) сообщает, в какой области вы заинтересованы. Хотя для базового подсчета SRack дает хороший ответ.

0 голосов
/ 13 июня 2018

Это должно сделать это для вас:

Upload.joins(:product).where(products: { catalog_id: 123 }).count

Использование joins создает INNER JOIN между двумя таблицами, что позволяет запрашивать таблицу продуктов, как указано выше.

Примечаниеединственное и множественное число product - объединения должны отражать ассоциацию (upload принадлежит one product), в то время как предложение where всегда использует имя таблицы, обычно в множественном числе.

SQL будет выглядеть примерно так:

SELECT "uploads".* FROM "uploads" 
INNER JOIN "products" 
ON "products"."id" = "uploads"."product_id" 
WHERE "products"."catalog_id" = 123

Если вам нужно больше информации о каталоге, вы также можете включить это, например, следующее:

Upload.joins(product: :catalog).where(products: { catalogs: { whatever: 'you want to query' } }).count

Имейте в виду, использование joins только для запроса, такого как этот.Если вам нужен доступ к атрибутам продукта или каталога, вы должны использовать другой подход, такой как includes, чтобы предварительно загрузить данные и избежать N + 1 запросов.Здесь хорошее чтение здесь , если вам интересно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...