Rails / Postgres 数据库 - 无法从数据库中检索正确的记录

Rails / Postgres database - can't retrieve correct records from db

我需要帮助解决数据库查询问题以生成正确的结果。这是一款使用 Rails 4.2.6、Ruby 2.2.4 和 Postgres 1.9.0 数据库开发的健身应用程序。当用户保存新的 body 测量值时,我会尝试显示自上次测量以来的变化(例如英寸)。问题是以前保存的记录的更改值在显示视图中计算不正确。

这是我目前编写的代码:

controllers/fitness_measurements_controller.rb:

before_action :get_second_latest_waist_measurement

def 

get_second_latest_waist_measurement     
  @waist_second_latest_measurement = @member.fitness_measurements.order(:created_at).offset(1).last.waist  || 0

end

fitness_measurements/show.html.erb:

<p>
  <strong>Change in waist since last measurement:</strong>
  <%= (@fitness_measurement.waist - @waist_second_latest_measurement).round(2) %> in
</p>

使用测试数据,这里有一个 table,其中包含我的数据库查询的结果。请注意 "Calc. Change" 列中的值。

+------------+-----------+------------------+--------------------+
|    Date    | Waist(in) | Calc. Change(in) | Correct Change(in) |
+------------+-----------+------------------+--------------------+
| 2016-10-01 |    37.5   |       +1.00      |        +1.00       |
+------------+-----------+------------------+--------------------+
| 2016-09-01 |    36.5   |       0.00       |        +3.00       |
+------------+-----------+------------------+--------------------+
| 2016-08-01 |    33.5   |       -3.00      |        +0.05       |
+------------+-----------+------------------+--------------------+
| 2016-07-01 |    33.0   |       -3.50      |        0.00        |
+------------+-----------+------------------+--------------------+

如您所见,除了最后一次保存的记录(2016-10-01)外,"Calc. Change"列中的值都不正确。我设计查询的方式有问题。

目前,我的查询检索比上次保存的测量值低 1 的记录作为 "second latest waist measurement." 在测试用例中,这是创建于 2016-09-01 的记录。这适用于保存到数据库的最后一条记录(在本例中为 2016 年 10 月 1 日),但是当我请求显示以前保存的记录的页面视图时会产生不正确的结果。例如2016-09-01创建的记录应该与2016--08-01创建的记录进行比较

在查询中使用 "offset(1)" 似乎是我问题的根源,但我不知道如何获得正确的记录。是遍历记录的解决方案吗?我不知道在这种情况下该怎么做?

我应该如何修复我的数据库查询以生成正确的更改值?如果有更好的方法,请告诉我。谢谢!

我不确定在 "Rails Way" 中执行此操作的最佳方法,但要在 Postgresql 中执行此操作,您可以使用 window 函数:

SELECT *, waist - LAG(waist) OVER (order by date) as change FROM fitness_measurements WHERE member_id = ?

在 PostgreSql 9 上试过3.x,它没有问题。没有在 Rails 中尝试过,但我想你必须做类似的事情:

sql = "SELECT *, waist - ..."
FitnessMeasurement.find_by_sql(sql)
...

控制器是该代码的错误位置 -- 为了更简单的实现,请向保存已保存值的模型添加一个方法。

def previous
  self.class.where(member: self.member).
             where("date < ?", self.date).
             order(date: :desc).
             take
end

这为您提供了该成员的先前实例,然后您可以从中读取测量值,允许如下逻辑:

@measurement.waist - @measurement.previous.waist