提问人:daveasdf_2 提问时间:11/8/2023 最后编辑:Holger Justdaveasdf_2 更新时间:11/8/2023 访问量:55
查询 Date.parse Rails 的位置
Query where Date.parse Rails
问:
我正在使用需要记录为 .event.start_time
"2023-11-07"
我需要根据 和 查找本月和上个月的所有事件,并在其中start_time
event.rained_out == false
event.start_time[0,4].to_i == Time.now.year && event.start_time[5,2] == Time.now.month || event.start_time[5,2] == Time.now.month && event.rained_out== false
我不是如何使用activerecord查询来实现这一点。
Event.where("start_time[5,2].to_i = ?", Time.now.month)
是语法错误
答:
我知道您数据库中的列是字符串类型,并且您希望查找日期以标识上个月或当前月份的特定字符串开头的所有行。start_time
我将首先为这些格式化的日期字符串前缀创建一个范围,如下所示:
date_prefixes = [1.month.ago, 1.month.since].map { |time| time.strftime('%Y-%m') }
#=> ["2023-10", "2023-12"]
prefixes_range = Range.new(*date_prefixes, exclude_end = true)
#=> "2023-10"..."2023-12"
然后,可以将该范围传递给查询,以查找该范围中包含的所有字符串。这将是所有以 或 开头但不以开头的开始日期,因为 .ActiveRecord
2023-10
2023-11
2023-12
exclude_end = true
Event.where(start_time: prefix_range)
这基本上可以转换为如下所示的 SQL 查询:
start_date >= '2023-10' AND start_date < '2023-12'
将所有内容放在一个范围内:
# in app/models/event.rb
scope :started_this_or_previous_month, -> {
where(
start_date: Range.new(
*[1.month.ago, 1.month.since].map { |t| t.strftime('%Y-%m') }, true
)
)
}
# use scope like this:
Event.started_this_or_previous_month.where(rained_out: false)
顺便说一句,即使你使用的宝石要求是一个字符串。您可能需要考虑向表中添加一个类型为 datetime 或 date 的列,并使两列保持同步。这将使数据库查询变得更加容易。start_date
start_at
start_on
评论
我假设这是您数据库中的文本列。start_time
出现语法错误的原因是您在 SQL 字段中编写了 ruby 代码。
请记住:您在 Arel 方法中放入的任何字符串(即 )都将按原样传递到底层 DBMS。where
where('...')
如果你真的想实现该算法,你应该在方法中使用有效的 SQL 语法:where
Event.where('SUBSTRING(start_time, 6, 2)::integer = ?', Time.now.month)
如果是日期/时间戳列,则可以编写:start_time
Event.where('EXTRACT(MONTH FROM start_time) = ?', Time.now.month)
上面的示例对 PostgreSQL DB 有效,如果您使用不同的内容,则应更正方法名称。
评论