我有一个BIGINT包含一个以毫秒为单位的日期。我希望按选定列created_at
的年份过滤记录。我正在使用MYSQL作为我的数据库。
这是我目前在我的控制器中所拥有的。
@agent = Agent.where('Time.at(created_at/1000).year = ?', '2017')
其中提供了以下错误:
Mysql2::Error: You have an error in your SQL syntax
答案 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>