【问题标题】:Custom select on join table连接表上的自定义选择
【发布时间】:2013-10-04 12:42:48
【问题描述】:

我正在使用 rails 3.2,并尝试使用 ActiveRecord 来查询我的数据库。 我有 2 个 activerecord 模型,Admin 和 Order:

class Admin < ActiveRecord::Base
  attr_accessible :email, :name
  has_many :orders
class Order < ActiveRecord::Base
  attr_accessible :operation
  belongs_to :admin

在我的例子中,order.operation 是一个字符串,代表订单类型。我正在尝试构建一个给我三列的查询:

admin.name, admin.orders.where(:operation => 'bonus').count, admin.orders.where(:operation => 'gift').count

有没有办法将其放入单个查询中?

编辑: 这是获取我需要的原始 sql:

SELECT t_a.admin_id_com, t_a.name, gb_f_f_gb_f_fi.bonus_count, gb_f_f_gb_f_fi.gifts_count 
FROM (
  SELECT f_fil.admin_id_gifts, f_fil.gifts_count, f_filt.admin_id_bonus, f_filt.bonus_count 
  FROM (
    SELECT admin_id as admin_id_gifts, count(distinct id) as gifts_count FROM orders WHERE operation = 'new gifts!' GROUP BY admin_id_gifts) 
  f_fil LEFT OUTER JOIN (
    SELECT admin_id as admin_id_bonus, count(distinct id) as bonus_count FROM orders WHERE operation = 'new bonuses!' GROUP BY admin_id_bonus) 
  f_filt ON (f_fil.admin_id_gifts = f_filt.admin_id_bonus)) 
gb_f_f_gb_f_fi LEFT OUTER JOIN (
  SELECT id AS admin_id_com, t_ad.name FROM admins t_ad) t_a ON (gb_f_f_gb_f_fi.admin_id_gifts = t_a.admin_id_com)

是否可以使用 ActiveRecord 构建这样的查询?

【问题讨论】:

  • 您是否希望基于admin.name 列的聚合列计算(即分组依据)?
  • 是的,.group(:admin_id) 会很好,但这不是我遇到问题的部分。
  • 您能告诉我您遇到了什么问题(例如,展示您尝试过的方法)吗?

标签: sql ruby-on-rails activerecord rails-activerecord


【解决方案1】:

试试这个:

@admins   = Admin.joins(:orders).
                 select("admins.id, admins.name, orders.id, 
                          SUM((orders.operation = 'bonus')::integer) AS bonus_count, 
                          SUM((orders.operation = 'gift')::integer) AS gift_count ").
                 group("admins.id ")

# access each columns as
admin.name, admin.bonus_count, admin.gift_count

其他选项是使用预加载,它将使用两个查询,但可能更快

@admins  = Admin.includes(:orders)

# in admin.rb
def orders_count(type)
  # Don't use where here as it would make a separate query instead of using eager loading records
   orders.select{|x| x.operation == type}.count
end 

# access each columns as
admin.name, admin.orders_count("bonus"), admin.orders_count("gift")

【讨论】:

  • 我已将SUM 更改为COUNT,它可以工作,但不是它应该的方式。它计算 bonus_countgift_count 中的所有订单。这是我得到的:t.map {|a| [a.name, a.bonus_count, a.gift_count]} - [["test", "10", "10"]]
  • 它不适用于SUM 吗? count 不起作用,因为它只会计算所有订单。 sum 的想法是 operations=bonus 在 true 时为 1,在 false 时为 0,因此求和它应该只计算带有 operation = bonus 的订单
  • 它不适用于 sum,至少它不适用于我的 heroku postgres =(
  • 对 heroku postgres 不熟悉,但似乎 postgres 具有求和功能。请参阅 here...当您使用 SUM 时它会说什么?
  • 所以,我终于有时间测试您的代码(第一个变体)。它有效,您只需将强制转换添加到整数:(orders.operation = 'bonus')::integer。纠正这一点,我会将您的答案标记为已接受。但是,我发现我的查询更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2015-12-19
相关资源
最近更新 更多