【问题标题】:Tricky Rails3/mysql query棘手的 Rails3/mysql 查询
【发布时间】:2011-06-15 06:57:30
【问题描述】:

在 rails 3(如果您想在查询中使用 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

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

这当然可以在 ruby​​ 中实现,例如:

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 次购买等),所以很遗憾我必须当场计算。

【问题讨论】:

  • 您能否制作一个表格来缓存此信息并在购买时生成它。这样就没有计算开销,您只需为用户计算一次状态。
  • 这不是直接回答,但要扩展 Devin 的评论,您可以向客户添加一个名为 repeat_status_date 的列,并在购买对象上使用 after_save 回调编写它。
  • 我会缓存它(或向客户添加一个“重复”字段),尽管只是为了这个简化的问题。回头客的标准可以由客户随时更改(2 次购买、3 次购买、4 次购买等),所以很遗憾我必须当场计算。

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


【解决方案1】:
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

我没有对此进行任何测试,所以我希望它有效。另外,我希望我能理解您要完成的工作。

但请注意,您不应该这样做,它会太慢。由于一天过去后数据永远不会改变,因此只需将其缓存为每一天。

【讨论】:

  • 我会缓存它(或向客户添加一个“重复”字段),尽管只是为了这个简化的问题。回头客的标准可以由客户随时更改(2 次购买、3 次购买、4 次购买等),所以很遗憾我必须当场计算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
相关资源
最近更新 更多