2010-10-26 52 views
2

我需要使用名为scope的rails找到与给定日期最近的日期。我需要在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}))"} 
} 

回答

3

如果您使用的是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

其中一个方案是沿的线使用的东西:

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

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

3

解决这样的:

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

因此我可以和其他命名范围随意限制结果的数量,这样就不会在所有记录迭代。

+0

小心,这只适用于SQLite AFAIK。对于Postgresql,它会是这样的:ABS(#{date.to_s(:db)} - value)。更多信息在这里:http://www.postgresql.org/docs/7.3/static/functions-formatting.html – gamov 2011-12-12 08:47:24

0

在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

+0

嗯..如果提供的日期晚于任何现有的日期呢? – randomguy 2011-04-04 12:56:31

相关问题