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), если применяется порядок по умолчанию по идентификатору.