0

我有以下半高级数据库查询,它通过过去 10 年的每小时价格并返回过去 7 天的每日平均价格:

averages = Trade.where('date >= ?', 7.days.ago).average(:price, :group => "DATE_TRUNC('day', date - INTERVAL '1 hour')")

这将返回date(当天)和averageprice这样的:

"2012-12-29 00:00:00"=>#<BigDecimal:7f97932be328,'0.2513458333 33333333E2',27(27)>

然后,我遍历每个响应并将它们保存为 TradeDailyAverage 模型中的新记录。

    # Loops through each daily average produced above 
    averages.each do |date, avg|

     # Converts the BigDecimal to Floating Point(?)
     averagefloat = avg.to_f

     # Rounds the Daily Average to only two decimal points
     dailyaverage = number_with_precision(averagefloat, :precision => 2)

     # Creates a new Object in the PpDailyAverage table  
     TradeDailyAverage.create(date: date, averageprice: dailyaverage)

这可行,但是由于这将是一个每小时的抽水任务,每小时都会有新的价格出现,我该如何更改它以首先找到一个 TradeDailyAverage date,如果它存在,更新averageprice属性,或者如果它不创建一个新记录'不存在。

Validate_uniqueness 在 TradeDailyAverage 模型上设置。

更新

当我这样做时,会出现 7 个项目,具有准确的平均值。但他们就是不会保存。当我添加时,newaverage.save!我收到“验证错误:日期已被占用!”

 newaverage = TradeDailyAverage.find_or_initialize_by_date(date: date)
          newaverage.averageprice = dailyaverage
          puts newaverage.date
          puts newaverage.averageprice

另外,如果我做 newaverage.new_record?曾经平均返回 TRUE

4

2 回答 2

2

我想你会想要这样的东西:

tda = TradeDailyAverage.first_or_initialize(date: date)
tda.averageprice = dailyaverage
tda.save
于 2013-01-04T18:33:05.440 回答
0

问题(感谢 Alex 的帮助)是由于日期时间的不同造成的。保存到 PG 数据库后,小时会在日期时间发生变化。这可能是由于数据库中的时区问题。因此,上面的代码找不到现有记录,因为它包含的每小时时间与数据库中保存的时间不同。

由于我正在生成每日平均值,因此我不需要时间,只需要日期列中的日期。因此,我将日期转换为日期以避免时差问题。我还用 Case 稍微更改了代码,以便我可以报告错误。我认为这不是很有效,但它现在正在工作。我相信只要将日期时间值转换为具有以下条件的日期,亚历克斯的上述解决方案也可能有效.to_date

# Loops through each daily average produced above 
    averages.each do |datetime, avg|

    # Converts the BigDecimal to Floating Point(?)
    avgfloat = avg.to_f

    # Rounds the Daily Average to only two decimal points
    avgprice = number_with_precision(avgfloat, :precision => 2)

    # Converts datetime to date since this will not work with datetime (PostgreSQL is time-zoned challenged)    
    avgdate  = datetime.to_date

        # These are printed to use for testing. 
      puts avgdate
      puts avgprice

      # Starts Case to either report an error, update an existing record, or create new.
      case

        when avgdate.blank? || avgprice.blank?
            puts "Something went terribly wrong with your seven day averages producing algorithm."

        when TradeDailyAverage.exists?(:date=>avgdate)
            updateavg = TradeDailyAverage.find_by_date(avgdate)
            updateavg.averageprice = avgprice
            updateavg.save

        else
            TradeDailyAverage.create(:date=>avgdate, :averageprice=>avgprice)

        end # Ends Case  

    end # Ends Loop for each Daily Average 
于 2013-01-05T18:28:29.140 回答