Ruby on rails подсчитывает и группирует

#sql #ruby-on-rails-3 #postgresql #group-by

#sql #ruby-on-rails-3 #postgresql #групповое по

Вопрос:

Необходимо создать запрос «Top 10», который работает с SQLite и Postgres.

Клиентская модель Клиент has_many :merchandises, :through => :orders, :source => :items

Я хочу сгруппировать товары, заказанные по product_id, получить количество для каждого и отсортировать по большинству продуктов, заказанных сверху, и ограничить до 10.

 Client.last.merchandises.group(:product_id).count(:quantity)
SELECT COUNT("items"."quantity") AS count_quantity, product_id AS product_id FROM "items" INNER JOIN "orders" ON "items"."order_id" = "orders"."id" WHERE "orders"."client_id" = 2 GROUP BY product_id
=> {1=>91, 2=>1, 12=>1, 32=>1, 33=>1, 34=>1, 37=>1, 75=>1, 84=>1, 85=>1}
  

Чего не хватает: сортировка по, ограничение до 10 и получение product.name наряду с подсчетом количества

Последняя разработка:

Элементы выбраны, но должны отображаться product.name

 class Client < ActiveRecord::Base 
def top_ten_products
  Item.find_by_sql(
    "SELECT i.product_id, sum(i.quantity) AS sum_quantity
    FROM   orders o
    JOIN   items i ON i.order_id = o.id 
    WHERE  o.client_id = 2 
    GROUP  BY 1
    ORDER  BY 2 DESC
    LIMIT  10;"
   )
 end
  

Вывод на консоль

 => [#<Item product_id: 1>, #<Item product_id: 37>, #<Item product_id: 75>, #<Item product_id: 12>, #<Item product_id: 32>, #<Item product_id: 33>, #<Item product_id: 2>, #<Item product_id: 34>, #<Item product_id: 84>, #<Item product_id: 85>] 
  

Клиент #показать

 <%= @client.top_ten_products %>
  

Ответ №1:

Предполагая, что product_id это столбец таблицы items , запрос может выглядеть следующим образом в PostgreSQL:

 SELECT i.product_id
      ,p.name
      ,sum(i.quantity) AS sum_quantity
FROM   orders o
JOIN   items i ON i.order_id = o.id 
LEFT   JOIN product p USING (product_id)
WHERE  o.client_id = 2 
GROUP  BY 1,2
ORDER  BY 3 DESC, 2 -- with same quantity, order by name
LIMIT  10;
  

Примечание:

Я изменил вашу агрегацию количества на a sum и добавил столбец с комментариями для count , поскольку я подозреваю, что у вас ошибочно было количество, в котором вы хотите получить сумму.

Правка2:

sum() подтверждено. Включено имя из таблицы product для каждого запроса.
LEFT JOIN это просто мера предосторожности для отсутствующих записей в таблице product , если ссылочная целостность гарантирована, вместо этого она может быть простой JOIN .

Комментарии:

1. Спасибо. Почти есть. Я отредактировал свой вопрос выше с помощью последней разработки

2. Спасибо за обновление, однако в разделе item нет столбца name. Столбец name является частью таблицы product. Пожалуйста, сообщите.

3. @Gaelle: я отредактировал свое предположение. Если это не так, вам необходимо предоставить информацию о том, как таблица product связана с таблицей item .

4. Вот где я не уверен. На данный момент у меня Item belongs_to :product ничего нет в таблице продуктов, поскольку я не уверен, как это должно быть установлено. Пожалуйста, сообщите. Спасибо

5. @Gaelle: вы видите столбец product_id в обеих таблицах? Итак, работает ли моя последняя версия? Просто попробуйте SELECT * FROM product LIMIT 10 и SELECT * FROM item LIMIT 10 посмотрите и выясните, как они связаны друг с другом.