我需要帮助排查数据库查询以生成正确的结果。这是一个使用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)”似乎是我的问题的根源,但我不知道如何获得正确的记录。是一个迭代记录的解决方案吗?在这种情况下,我对如何做到这一点很困惑?
如何修复数据库查询以生成正确的更改值?如果有更好的方法,请告诉我。谢谢!
答案 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