【问题标题】:I need to find closest date in a rails app我需要在 Rails 应用程序中找到最近的日期
【发布时间】:2011-04-30 21:56:28
【问题描述】:

我需要使用名为 scope 的 rails 找到最接近给定日期的日期。

对于 MySql,我可以使用 DATEDIFF,但我想保持数据库不可知论,以下不适用于 Sqlite:

named_scope :closest_to, lambda { |*args|
  date  = args.first
  count = args[1] || 1
  {:limit => count, :order => "ABS(DATEDIFF(hour, date_field, #{date.to_formatted_s :db}))"}
}

【问题讨论】:

    标签: sql ruby-on-rails sqlite activerecord


    【解决方案1】:

    如果您使用 Postgres,则必须使用 EXTRACT(EPOCH FROM ()) 将间隔转换为秒,因为 ABS 只接受数字作为参数。

    scope :order_by_closest_to, lambda { |date|
      {:order => %{ABS(EXTRACT(EPOCH FROM ('#{date.to_formatted_s(:db)}'::timestamp - some_timestamp_column))) asc} }
    }
    

    我认为没有任何与数据库无关的方式来执行此查询,因为 mysql、postgres 和 sqlite 之间的函数和转换不同。

    【讨论】:

      【解决方案2】:

      这样解决:

      named_scope :order_by_closest_to, lambda { |date|
        {:order => %{ABS(strftime('%s', "#{date.to_formatted_s(:db)}") - strftime('%s', value)) asc} }
      }
      

      因此我可以与其他命名范围混合并限制结果的数量,这样它就不会遍历所有记录。

      【讨论】:

      【解决方案3】:

      一种选择是使用以下内容:

      :limit => count, :select => "*, abs(date('#{date.to_formatted_s :db}') - date('#{date_field}')) as date_diff", :order => "date_diff"

      虽然可能有点数据库密集型,因为它必须从所有记录中计算 date_diff 字段。

      【讨论】:

        【解决方案4】:

        在 SQL 中,上述问题通常通过以下方式解决:

        SELECT *
        FROM my_table
        WHERE start_date = ( SELECT MAX(start_date) FROM my_table WHERE start_date <= '2011-02-18' )
        

        这适用于所有支持子查询的数据库(SQLite 不支持)。此处对“时间点”SQL 进行了很好的概述:http://www.orafaq.com/node/1834

        【讨论】:

        • 嗯.. 如果提供的日期晚于任何现有日期怎么办?
        猜你喜欢
        • 1970-01-01
        • 2021-04-23
        • 2016-09-17
        • 1970-01-01
        • 2015-12-03
        • 2018-09-06
        • 1970-01-01
        • 1970-01-01
        • 2014-04-28
        相关资源
        最近更新 更多