毫秒转换并获得年份

时间:2017-11-21 03:44:47

标签: mysql ruby-on-rails ruby-on-rails-5

我有一个BIGINT包含一个以毫秒为单位的日期。我希望按选定列created_at的年份过滤记录。我正在使用MYSQL作为我的数据库。

这是我目前在我的控制器中所拥有的。

@agent = Agent.where('Time.at(created_at/1000).year = ?', '2017')

其中提供了以下错误:

Mysql2::Error: You have an error in your SQL syntax

2 个答案:

答案 0 :(得分:2)

除非你不知道,否则我不认为你可以在比较那样的地方进行Time.at

一种方法是逆转比较,并将年份变为自纪元以来的毫秒:

comparison_time = (Time.new(2017, 1, 1).to_f * 1000).to_i
@agent = Agent.where("created_at = ?", comparison_time)

注意:如果您的行的时间戳与年份完全对应,则可以使用与示例中相同的等比较。否则,您可能需要开始日期和结束日期,以便您可以返回范围。例如:

start_time = (Time.new(2017, 1, 1).to_f * 1000).to_i
end_time = (Time.new(2018, 1, 1).to_f * 1000).to_i
@agent = Agent.where("created_at >= ? AND created_at <= ?", start_time, end_time)

另一种方法是循环遍历所有代理,将每个代理的created_at转换为DateTime并与2017进行比较。但是,如果你有一个大表,这可能需要大量的内存,因为Rails会做与MySQL相反的操作。

答案 1 :(得分:2)

数据库不理解像Time.at(created_at/1000).year这样的Ruby代码,所以你不能在这样的where调用中使用它,where的那种形式适用于的片段SQL ,而不是 Ruby

您可以让数据库从“epoch”created_at值以来的“毫秒”中提取年份。您可以使用具有相应格式字符串的MySQL from_unixtime函数一步完成此操作:

Agent.where("from_unixtime(created_at/1000, '%Y') = ?", '2017')

这与您尝试将Ruby代码发送到数据库的过程几乎相同。

当然,您可能更喜欢在Ruby中完成工作,如Charlie Weems's answer中所述。

如果你这么做很多,并且在WHERE子句中没有别的东西来减少你正在查看的行数,你可能想要比较每种方法与你拥有的任何索引的交互方式。< / p>