在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.all
和Purchase.all
上触发查询,然后在ruby中进行一堆计算。我更喜欢在mysql中进行选择,分组和计算,因为它不仅速度快,而且还减少了数据库中的带宽。在大型数据库中,上面的代码基本上是无用的。
我已经尝试了一段时间来在rails / active_record中召唤查询,但即使使用了漂亮的meta_where gem也没有运气。如果必须,我也会接受纯mysql查询的解决方案。
编辑:我会缓存它(或向客户添加“重复”字段),但仅限于此简化问题。重复客户的标准可以在任何时候由客户改变(2次购买,3次购买,4次购买等),所以不幸的是我必须当场计算。
答案 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
我没有丝毫测试过,所以我希望它有效。另外,我希望我理解你要完成的任务。
但请注意,你不应该这样做,它会太慢。由于数据在一天过去后永远不会改变,所以只需每天缓存一次。