繁体   English   中英

.where中两个日期之间的rails差异

[英]rails difference between two dates inside .where

这是我的逻辑,我想将最昂贵的4个手机最接近特定的手机@mobile但在一种情况下,两个手机的发布日期之差不超过一年半。这是查询

high = Mobile.where("price >= #{@mobile.price} AND id != #{@mobile.id} AND visible = true").where("ABS(release_date - #{@mobile.release_date}) > ?", 18.months).order(price: :ASC).first(4)

第一个.where()可以正常工作,但是第二个却无法工作,并且出现此错误

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00 UTC) > 46656000) ORDER BY `mobiles`.`price` ASC LIMIT 4' at line 1: SELECT `mobiles`.* FROM `mobiles` WHERE (price >= 123123.0 AND id != 11 AND visible = true) AND (ABS(release_date - 2016-04-10 00:00:00 UTC) > 46656000) ORDER BY `mobiles`.`price` ASC LIMIT 4

我想现在您可以理解我的逻辑了。 实现它的正确语法是什么?

这里有几个提示:

  • 使用"#{}"运算符将变量连接到查询中是一种危险的做法。 这样做会绕过查询参数化,并可能使您的应用程序无法进行SQL注入 而是使用"?" 在您的where子句中。
  • MySQL给您一个错误的原因是因为您正在将字符串连接到查询中,而没有将其封装在引号中。

考虑到这两点,我将以如下方式重构您的查询开始:

high = Mobile.where("price >= ?", @mobile.price)
         .where.not(id: @mobile.id)
         .where(visible: true)
         .where("ABS(release_date - ?) > 46656000", @mobile.release_date)
         .order(price: :ASC).first(4)

您会注意到,我用18.months替换了46656000 这样可以在Rails应用程序中节省几个时钟周期。 根据您的数据库架构,最后的where子句可能不起作用。 下面的修改可能会更好地工作。

作为进一步改进,您可以重构您的last where子句以查找发布日期,该发布日期在@mobile.release_date之前的18个月与之后的18个月之间。 这样就不必对每条记录进行数学运算,从而节省了MySql数据库的时间,并且可能导致更好的性能:

.where(release_date: (@mobile.release_date - 18.months)..(@mobile.release_date + 18.months) )

我不知道您的数据库架构,因此您可能会遇到上述代码的日期转换问题。 我建议您在Rails控制台中使用它。

使用范围查询日期/时间之间:

Mobile.where("price >= ?", @mobile.price)
      .where.not(id: @mobile.id)
      .where(release_date: 18.months.ago..Time.now)
      .order(price: :ASC)
      .first(4)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM