Rails ActiveRecord Выполняет группу, сумму и количество в одном запросе

У меня есть две таблицы,

Order (ID, Value)

и

OrderType (ID, Name [Quote, Sale, Purchase, etc])

Я хочу получить общее количество заказов в каждом типе (количество) и общее значение этих заказов на тип (сумму)

Я могу получить их индивидуально, используя

Order.group(:order_type).count(:id)

и

Order.group(:order_type).sum(:value)

Я хотел бы выполнить их в одном запросе, эквивалентном следующему SQL

SELECT
  order_types.id, Count(*) as total_count, Sum(orders.value) As total_value
FROM
  order
JOIN
  order_types ON orders.order_type_id = order_types.ID
GROUP BY
  order_types.id

Запрос также должен вернуть полный объект OrderType, чтобы я мог отображать имя в моем представлении

Ответ 1

Так как ActiveRecord не поддерживает несколько функций агрегации в одном запросе, для этого вам нужно сделать немного необработанного SQL.

grouped_sales = OrderType
  .select('order_types.id, order_types.name, 
     sum(orders.value) as sale, count(*) as purchase')
  .join('JOIN orders ON orders.order_type_id = order_types.id')
  .group('order_types.id')

Обратите внимание на то, что вам нужно использовать существующий столбец в OrderType как псевдоним для ваших агрегированных столбцов. Здесь вы также получите объект OrderType.

Чтобы получить доступ к результату:

id -> grouped_sales.first.id
name -> grouped_sales.first.name
total orders -> grouped_sales.first.sale
order value -> grouped_sales.first.purchase

Ответ 2

Есть даже лучшее решение, просто:

.pluck('sum(orders.value), count(*)').first

Ответ 3

В настоящее время работа с pluck + arel.

model = Model.arel_table
Model.group(:order_type).pluck(model[:id].count, model[:value].sum)

Также может потребоваться добавление с помощью .order(: order_type), если применяется порядок по умолчанию по идентификатору.