【问题标题】:Rails / Postgres database - can't retrieve correct records from dbRails / Postgres 数据库 - 无法从数据库中检索正确的记录
【发布时间】:2016-10-10 16:23:58
【问题描述】:

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

这是我目前编写的代码:

控制器/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)外,“Calc. Change”列中的值不正确。我设计查询的方式有问题。

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

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

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

【问题讨论】:

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


    【解决方案1】:

    我不确定以“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)
    ...
    

    【讨论】:

    • 感谢您的回复。我会看看这个,看看我是否能弄清楚如何将它应用到我的 Rails 项目中。需要弄清楚如何修改我的查询方法代码。
    • 原始 SQL 导致以下错误:语法错误,意外',' sql = SELECT *,腰 - LAG(waist) OVER (ord...
    • 你真的省略了引号吗?这是 ruby​​ 错误还是 postgres 错误?我应该尝试在“rails dbconsole”中运行 SQL 以使其首先工作。
    • 我运行了没有引号的 SQL。我决定接受@David Alridge 解决方案……它比我原来的方法更干净/更好。不过,感谢您的帮助。
    • 我无法评论 David Aldridge 的回答(声誉不够),但我会考虑在 .take 之前添加一个 .limit(1) ,否则它看起来会返回所有数据库中以前的 Fitness_measurements 而不是一个。
    【解决方案2】:

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

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

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

    @measurement.waist - @measurement.previous.waist
    

    【讨论】:

    • 感谢您提供此解决方案!这种方法比我以前的方法更干净,也更好。它工作得很好。太棒了。
    猜你喜欢
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 2011-11-02
    相关资源
    最近更新 更多