簡體   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