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

问题描述:

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

这里是我到目前为止编码:

控制器/ 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月1日),在“计算。更改”列中的值是不正确的。我设计查询的方式有问题。

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

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

我应该如何解决我的数据库查询以生成正确的更改值?如果有更好的方法,请让我知道。谢谢!

控制器是该代码错误的地方 - 一个更简单的实现添加一个方法来保存的保存模型值。

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

这给你的成员,从中可以再读取测量以前的实例,使逻辑,如:

@measurement.waist - @measurement.previous.waist 
+0

谢谢你的解决方案!这种方法比我所拥有的更清洁,更好。它效果很好。真棒。 – codeinspired

我不知道的一个“Rails的路”要做到这一点的最好办法,但只做到这一点在PostgreSQL,您可以使用窗口函数:

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) 
... 
+0

感谢您的回复。我会看看这个,看看我能不能找出如何将这个应用到我的Rails项目。需要弄清楚如何修改我的查询方法代码。 – codeinspired

+0

原始的SQL会导致以下错误:语法错误,意外','sql = SELECT *,腰部 - LAG(腰部)OVER(ord ... – codeinspired

+0

您是否实际上忽略了引号?是一个红宝石错误还是一个postgres错误?我应该尝试在“rails dbconsole”中运行SQL以使其首先工作。 –