Tricky Rails3 / mysql查询

时间:2011-06-14 01:11:56

标签: mysql ruby-on-rails ruby-on-rails-3

在rails 3中(如果您想在查询中使用meta_where gem,也会使用meta_where gem),我得到了一个非常棘手的查询,我一直在为此烦恼:

假设我有两个型号,客户和购买,客户有很多购买。让我们将至少2次购买的客户定义为“repeat_customer”。我需要在过去3个月内找到每天重复客户的总数,例如:

Date    TotalRepeatCustomerCount
1/1/11  10 (10 repeat customers by the end of 1/1/11)
1/2/11  15 (5 more customer gained "repeat" status on this date)
1/3/11  16 (1 more customer gained "repeat" status on this date)
...
3/30/11 150
3/31/11 160

基本上我需要根据第二次购买的创建日期对客户进行分组,因为这是他们“获得重复状态”的时间。

当然,这可以用红宝石来实现,例如:

Customer.includes(:purchases).all.select{|x| x.purchases.count >= 2 }.group_by{|x| x.purchases.second.created_at.to_date }.map{|date, customers| [date, customers.count]}

但是,上面的代码会在同一行Customer.allPurchase.all上触发查询,然后在ruby中进行一堆计算。我更喜欢在mysql中进行选择,分组和计算,因为它不仅速度快,而且还减少了数据库中的带宽。在大型数据库中,上面的代码基本上是无用的。

我已经尝试了一段时间来在rails / active_record中召唤查询,但即使使用了漂亮的meta_where gem也没有运气。如果必须,我也会接受纯mysql查询的解决方案。

编辑:我会缓存它(或向客户添加“重复”字段),但仅限于此简化问题。重复客户的标准可以在任何时候由客户改变(2次购买,3次购买,4次购买等),所以不幸的是我必须当场计算。

1 个答案:

答案 0 :(得分:0)

SELECT p_date, COUNT(customers.id) FROM
(
  SELECT p_date - INTERVAL 1 day p_date, customers.id
  FROM
     customers NATURAL JOIN purchases
     JOIN (SELECT DISTINCT date(purchase_date) p_date FROM purchases) p_dates
  WHERE purchases.purchase_date < p_date
  GROUP BY p_date, customers.id
  HAVING COUNT(purchases.id) >= 2
) a
GROUP BY p_date

我没有丝毫测试过,所以我希望它有效。另外,我希望我理解你要完成的任务。

但请注意,你不应该这样做,它会太慢。由于数据在一天过去后永远不会改变,所以只需每天缓存一次。