【问题标题】:Complex time-series statistical aggregation involving polymorphic associations涉及多态关联的复杂时间序列统计聚合
【发布时间】:2011-09-08 11:42:20
【问题描述】:

好的。请耐心等待,因为我需要提供大量上下文细节,然后才能为我的问题寻求合理的答案。

我有一个网站,可让您进行每日选股。它的工作方式是提示您在当天对峙的公司之间进行选择。例如,通用电气与 IBM。您可以选择两种类型:表现(哪只股票表现更好?)和总交易量(合并后的股票交易量会高于还是低于 X?)。每天为您提供 100 个虚拟美元来进行选择。

最终,我们的目标是在以下时间段内跟踪哪个用户在各种类别(如下所述)中每次选择赚的钱最多:5 天、15 天、30 天、90 天、180 天、1 年, 整天。计算每次选秀赚多少钱非常简单。这是赚(或赔)的总金额/选秀次数。

现在,用户选择的每家公司都属于一个分类层次结构。通常,分类层次结构如下所示:

部门 --> 主要组 --> 行业组 --> 分类 --> 公司

这里有一些例子:

  • 采矿 --> 金属采矿 --> 铁矿石 --> 褐矿 --> 公司 A
  • 采矿 --> 金属采矿 --> 铁矿石 --> 褐矿开采 --> 公司 B
  • 采矿 --> 金属采矿 --> 铁矿石 --> 褐铁矿 --> 公司 C
  • 采矿 --> 金属采矿 --> 铁矿石 --> 褐铁矿 --> 公司 D
  • 制造 --> 烟草制品 --> 雪茄 --> Stogies --> 公司 E
  • 制造 --> 烟草制品 --> 雪茄 --> Stogies --> F公司
  • 制造 --> 烟草制品 --> 雪茄 --> Cigarillos --> 公司 G
  • 制造 --> 烟草制品 --> 雪茄 --> Cigarillos --> 公司 H
  • ……等等……

每个类别都有一个模型(当然还有对应的表),它们是相关联的(想想foreign_key),就像你在上面看到的那样。

Matchup 有一个模型,每条记录代表当天要对战的公司。每条记录都记录了每家公司的起始和最终股票价格,以及总交易量。

每场比赛都有一个或多个 :pick_prices 可以全天变化。通常,每场比赛都有一个性能选择价格和一个总数量选择价格。价格决定了选秀权的成本以及正确选秀权的收入。 (现在,这只是背景信息。您无需担心那些特定的价格计算。)

在交易日结束时,用户的选择得到解决。 Picks 在 Pick 模型中表示,具有以下属性:

  • user_id
  • amount_spent(例如,10 美元)
  • 结果(例如,赢、输)
  • 挑选(例如,A 公司)
  • matchup_id
  • pick_price_id
  • amount_won
  • 已解决(真或假)
  • created_at
  • updated_at

目前,当每个pick被解析时,都会更新另一个名为pick_records的表,该表具有以下属性:

  • user_id
  • recordable_id
  • recordable_type(部门或主要组或行业组或分类或公司)
  • 选秀次数(总选秀次数,与选秀类型无关)
  • 赢了(赢得的总选秀权,无论选秀类型如何)
  • lost(无论选择类型如何,总选择丢失)
  • 钱(赢得的总钱数)
  • money_per_pick(金钱/挑选)
  • performance_picks
  • performance_won
  • performance_lost
  • performance_money
  • performance_money_per_pick
  • volume_picks
  • volume_won
  • volume_lost
  • volume_money
  • volume_money_per_pick
  • created_at
  • updated_at

如您所知,这是一个多态模型。该表汇总了所有时间的选择记录统计信息。

所以现在挑战来了:

鉴于现有的设计,我需要做些什么才能捕获用户在以下时间段内的选择记录:5 天、15 天、30 天、90 天、180 天、1 年、所有-时间?它需要简单、高效、快速!

我目前在 MySQL DB 上运行 Rails 2.3.11。

【问题讨论】:

  • 注意:上面的每个表都有时间戳——created_at、updated_at。
  • 希望一些答案对你有用;让我知道哪些有效,哪些无效,以便我可以为您提供符合您需要的答案。
  • +1 将你的一半代表用于赏金。
  • 好吧,如果有人愿意花时间阅读所有内容并提供答案,最好让他们的努力值得!
  • 您有大小有限的数据库吗?如果是这样,您将希望实现一种方法来汇总和清除 Pick 数据,并实现一种基于用户平均值计算用户得分/排名/等的方法。是这样吗?

标签: mysql sql ruby-on-rails polymorphic-associations aggregation


【解决方案1】:

我认为不需要 table pick_records。
您可以在任意天数内执行这样的查询:

SELECT 
   user_id
   ,sum(amount_spent) 
   ,sum(IF(result = 'WON',1,0)) as WON_count
   ,sum(IF(result = 'LOST',1,0)) as LOST_count
   ,pick 
   /*matchup_id*/
   ,sum(pc.price) as price
   ,sum(IF(result = 'WON'),amount_won,0)) as amount_won
   ,sum(IF(result = 'LOST'),amount_won,0)) as amount_lost
   ,sum(IF(result = 'WON'),amount_won,-amount_won)) as nett_amount
FROM picks
INNER JOIN pick_price pc ON (pc.id = user.pick_price_id)
WHERE created_at BETWEEN DATE_SUB(NOW(), INTERVAL 5 DAY) AND NOW()
  AND resolved = 'true'
GROUP BY user_id, pick

【讨论】:

  • 我自己倾向于直接使用 SQL,所以我喜欢你的想法
【解决方案2】:

不确定我的问题是否正确,但是...

@records=Pick_record.all(:conditions => ["user_id = ?", user_id],
                         :group => "date(created_at)", 
                         :having => ["created_at > ?", 5.days.ago])

【讨论】:

    【解决方案3】:

    如果我理解正确,现在每个用户只有一个pick_record,它包含他的总选择的概述,并在解决选择时更新。

    由于pick_record的内容是可以计算出来的,所以它只是用来缓存和确保你可以快速提供数据/报告。

    为了解决您的问题,我提出以下建议:

    在整个生命周期内,我将有一个您感兴趣的每个时间段的 pick_record,而不是单个 pick_record。因此,您将有一个 pick_record 包含过去 4 天的结果,一个包含结果的结果过去 14 天,29 天......您每天计算一次的那些,最好是在晚上(或当您的网站使用率低时)。当必须显示选定时间段的报告时,您只需添加当天的结果即可!

    所以,回顾一下:

    1. 为每个感兴趣的时间段引入一个pick_record(添加一个指示时间段的字段:5、15、30、...)
    2. 每天预计算一次结果(后台作业,例如 resque 或延迟作业)
    3. 检索周期结果时,只需添加当天的结果

    你怎么看?

    【讨论】:

      猜你喜欢
      • 2012-06-11
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多