如何在rails中添加条件where子句

Posted

技术标签:

【中文标题】如何在rails中添加条件where子句【英文标题】:How to add conditional where clauses in rails 【发布时间】:2012-07-26 05:53:00 【问题描述】:

我是 Rails 新手,正在尝试使用 Rails 对表执行搜索,而我只是使用我的 sql 知识来执行此操作。但这看起来不像是 rails 或 ruby​​...

有没有更好的方法来做我在下面做的事情? (基本上,只有在填写日期参数时才将日期参数传递给 sql)

def search(begin_date=nil, end_date=nil)

    subject = " and created_at "

    if !(begin_date.nil? || end_date.nil?)
      where_part = subject + "BETWEEN :begin_date AND :end_date"
    else if (begin_date.nil? && end_date.nil?) 
      where_part = ""
    else if(begin_date.nil?)
      where_part = subject + " <= :end_date"
    else if (end_date.nil?)
      where_part = subject + " >= :begin_date"
    end
    end
    end
    end

    User.joins(places: containers: label: :user).where("users.id= :user_id "+where_part, user_id: self.id, begin_date:begin_date, end_date:end_date).group(...).select(...)
end

编辑

用户.rb

has_many :containers
has_many :user_places
has_many :places, through: :user_places
has_many :labels

place.rb

has_many :containers
has_many :user_places
has_many :users, through: :user_places

容器.rb

belongs_to :label
belongs_to :place
belongs_to :user

标签.rb

belongs_to :user
has_many :containers

基本上,我想计算给定用户标签内或与每个位置有直接关系的容器数量,并希望能够按开始和结束日期对其进行过滤。

这两个日期都可能为零,所以我需要在我的“查询”中解决这个问题。

我的问题是:我怎样才能做到这一点?我看了一下http://guides.rubyonrails.org/active_record_querying.html,也许我可以在这里的某个地方使用except命令……但是这种关系模型似乎有点复杂,用ActiveRecord来做这件事……我可以怎么做?,我真的认为我应该使用ActiveRecord ,但是怎么做?

谢谢

【问题讨论】:

[这里是一个很好的例子,说明如何使用活动记录进行连接][1] [1]:***.com/questions/764538/… 嗨,我的问题不在于连接...我只是没有写它们,因为它们不相关。我的事情是条件搜索参数 @itsalltime - 我认为 Bob 想说的是 - 为什么不使用 Active Record 而不是直接编写 SQL? guides.rubyonrails.org/active_record_querying.html 【参考方案1】:

我想不出你为什么要在代码中生成 SQL 的一个重要原因。 Active Record 似乎是满足您需求的更有效的解决方案,除非您有理由不能使用它。

Link explaining how to join tables with active record

【讨论】:

我实际上对如何使用连接有一些疑问,但我想我找到了一种方法来解决我想要的问题,因为我在我编辑的答案中发布了。我的东西实际上是条件搜索参数。 哦,像这样的情况:rigelgroupllc.com/blog/2014/09/14/…【参考方案2】:

您可以对一个查询应用多个 where 调用,以便构建基本查询:

query = User.joins(...)
            .group(...)
            .select(...)
            .where('users.id = :user_id', :user_id => self.id)

然后根据您的日期间隔添加另一个 where 电话:

if(begin_date && end_date)
  query = query.where(:created_at => begin_date .. end_date)
  # or where('created_at between :begin_date and :end_date', :begin_date => begin_date, :end_date => end_date)
elsif(begin_date)
  query = query.where('created_at >= :begin_date', :begin_date => begin_date)
elsif(end_date)
  query = query.where('created_at <= :end_date', :end_date => end_date)
end

每个where 调用都会使用 AND 为您的整体 WHERE 子句添加另一部分,例如:

q = M.where(a).where(b).where(c)

WHERE a AND b AND c一样。

【讨论】:

嗨,这个答案很棒。谢谢。看来我不能使用 begin_date .. end_date (并且必须使用空白?而不是 nil),因为我正在从文本字段中收集日期时间并在本地转换它们。 if !begin_date.blank? begin_date = DateTime.strptime("#begin_date 00:00:00", "%m/%d/%Y %H:%M:%S").to_datetime end我最终使用了您的替代建议:or where('created_at between :begin_date and :end_date', :begin_date =&gt; begin_date, :end_date =&gt; end_date) @itsalltime:如果begin_dateend_date 是真正的日期对象,则使用begin_date .. end_date 应该可以工作,但看起来你实际上有字符串。我建议在使用它们之前将它们转换为日期对象,这样您就只需要在一个地方担心日期格式问题。 嗨,我确实使用上面发布的函数转换它们,但即便如此 begin_date .. end_date 不起作用,这就是为什么我不得不选择替代方法 我想这一定是其他错误,因为现在看起来还可以。我现在的问题是“created_at”正在应用于用户表,我希望它应用于容器......我该怎么做?

以上是关于如何在rails中添加条件where子句的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4:将 where 子句添加到连接条件

在Oracle View的where子句中添加条件

如何使用 AREL 执行条件 where 子句

如何在 WHERE 子句中使用条件不同的列?

向 where 子句添加条件

Rails 在带有连接的 where 子句中运行 AND 查询