问题描述
|
在rails 3中(如果您想在查询中使用它,也可以使用Meta_where gem),我得到了一个非常棘手的查询,我一直在努力:
假设我有两个模型,客户和购买,客户有很多购买。让我们将至少两次购买的客户定义为“ 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
和ѭ3the的同一行上进行查询,然后在ruby中进行一堆计算。我更喜欢在MysqL中进行选择,分组和计算,因为它不仅速度更快,而且还减少了数据库的带宽。在大型数据库中,上面的代码基本上没有用。
我已经尝试了一段时间来构想一下rails / active_record中的查询,但是即使使用了不错的Meta_where gem也没有运气。如果需要,我也将接受纯mySQL查询中的解决方案。
编辑:我会缓存它(或向客户添加一个“ repeat”字段),尽管仅用于此简化问题。重复客户的标准可以在任何时候由客户更改(2次购买,3次购买,4次购买等),因此不幸的是,我确实必须在现场进行计算。
解决方法
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
我没有丝毫的测试,所以我希望它能工作。另外,我希望我能理解您要完成的工作。
但是请注意,您不应该这样做,因为它太慢了。由于数据一旦经过一天就永远不会改变,因此只需每天对其进行缓存。