查询 Date.parse Rails 的位置

Query where Date.parse Rails

提问人:daveasdf_2 提问时间:11/8/2023 最后编辑:Holger Justdaveasdf_2 更新时间:11/8/2023 访问量:55

问:

我正在使用需要记录为 .event.start_time"2023-11-07"

我需要根据 和 查找本月和上个月的所有事件,并在其中start_timeevent.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)

是语法错误

Ruby-on-Rails Ruby 日期时间 ActiveRecord

评论


答:

2赞 spickermann 11/8/2023 #1

我知道您数据库中的列是字符串类型,并且您希望查找日期以标识上个月或当前月份的特定字符串开头的所有行。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"

然后,可以将该范围传递给查询,以查找该范围中包含的所有字符串。这将是所有以 或 开头但不以开头的开始日期,因为 .ActiveRecord2023-102023-112023-12exclude_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_datestart_atstart_on

评论

0赞 daveasdf_2 11/8/2023
美丽,谢谢
1赞 Andrea Salicetti 11/8/2023 #2

我假设这是您数据库中的文本列。start_time

出现语法错误的原因是您在 SQL 字段中编写了 ruby 代码

请记住:您在 Arel 方法中放入的任何字符串(即 )都将按原样传递到底层 DBMS。wherewhere('...')

如果你真的想实现该算法,你应该在方法中使用有效的 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 有效,如果您使用不同的内容,则应更正方法名称。

评论

0赞 daveasdf_2 11/8/2023
我很感激,谢谢。这也是正确的,但我已经实现了 spickermann 的解决方案,因为会有额外的查询,而且我还不流利的 PostgreSQL