Rails ActiveRecord在一个查询中执行Group,Sum和Count

时间:2014-11-26 09:53:37

标签: ruby-on-rails ruby 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对象,以便在视图中显示名称

3 个答案:

答案 0 :(得分:11)

由于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

答案 1 :(得分:4)

还有更好的解决方案,只是:

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

答案 2 :(得分:0)

如今,puck + arel会做这项工作。

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

如果根据ID应用了默认排序,则可能还需要附加.order(:order_type)。