Rails / Postgres数据库 - 无法从db

时间:2016-10-10 16:23:59

标签: sql ruby-on-rails rails-activerecord postgresql-9.1

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

这是我到目前为止编码的内容:

控制器/ 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>

使用测试数据,这是一个包含我的数据库查询结果的表。请注意“计算更改”列中的值。

+------------+-----------+------------------+--------------------+
|    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)之外,“计算更改”列中的值不正确。我如何设计查询有问题。

目前,我的查询检索上次保存的测量值下方1的记录,作为“第二次最新腰围测量值”。在测试用例中,这是2016-09-01创建的记录。这适用于保存到数据库的LAST记录(在本例中为2016-10-01),但在请求显示先前保存记录的页面视图时会产生不正确的结果。例如,2016-09-01创建的记录应与2016-08-01创建的记录进行比较。

在查询中使用“offset(1)”似乎是我的问题的根源,但我不知道如何获得正确的记录。是一个迭代记录的解决方案吗?在这种情况下,我对如何做到这一点很困惑?

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

2 个答案:

答案 0 :(得分:1)

我不确定以“Rails方式”执行此操作的最佳方法,但只需在Postgresql中执行此操作即可使用窗口函数:

DetailViewController1

在PostgreSql 9.3.x上试过这个并且没有问题。没有在Rails中尝试过,但我想你必须做类似的事情:

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

答案 1 :(得分:0)

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

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

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

@measurement.waist - @measurement.previous.waist