我正在尝试根据关联中的查询进行复杂的搜索。
事件 belongs_to :user / 用户 has_many :events
从字面上看:
query = User.where(:name => 'Bob')
query = query.joins(:events).where('COUNT(events.start_at > #{Time.now}) = 0')
我尝试了几种方法,但似乎都没有奏效。非常感谢帮助。
提前致谢。
我正在尝试根据关联中的查询进行复杂的搜索。
事件 belongs_to :user / 用户 has_many :events
从字面上看:
query = User.where(:name => 'Bob')
query = query.joins(:events).where('COUNT(events.start_at > #{Time.now}) = 0')
我尝试了几种方法,但似乎都没有奏效。非常感谢帮助。
提前致谢。
您需要使用范围来允许这种链接:
在用户模型中:
scope :with_name, lambda { |name| where(:name => name) }
在代码中:
query = User.with_name('Bob')
query = query.joins(:events).where('COUNT(events.start_at > #{Time.now}) = 0')
我注意到您的查询编写方式存在一些问题,但我认为修复它们不会解决您的问题。尽管如此,希望知道这些东西会让你更接近!
首先,您需要双引号以使 Ruby 尊重您的 #{} 插值:
打开 IRB 并尝试:
1.9.3p194 :001 > 'COUNT(events.start_at > #{Time.now}) = 0'
这将输出:
"COUNT(events.start_at > \#{Time.now}) = 0"
请注意,没有任何变化,因为我们有单引号。
现在让我们尝试使用双引号,我们更接近一点:
1.9.3p194 :002 > "COUNT(events.start_at > #{Time.now}) = 0"
这次我们看到:
"COUNT(events.start_at > 2012-09-24 14:47:52 -0700) = 0"
但这仍然行不通,因为 SQL 需要在您的时间戳周围加上引号以进行比较。
我们可以手动处理,如下所示:
1.9.3p194 :003 > "COUNT(events.start_at > '#{Time.now}') = 0"
生成:
"COUNT(events.start_at > '2012-09-24 14:49:31 -0700') = 0"
但这可能不适用于所有 SQL - 我知道 Postgres 需要单引号包围文字,但 MySQL 可能更喜欢双引号,或者可能无关紧要。
处理这个问题的最好方法是让 Rails 解决这个问题。我们这样做的方式是使用 ? 我们的 SQL 查询字符串中的运算符:
where('COUNT(events.start_at > ?) = 0', Time.now)
Rails 将生成并发送到您的 SQL 数据库的输出,如下所示:
"WHERE COUNT(events.start_at > '2012-09-24 14:49:31 -0700') = 0"
希望有帮助!
我认为这就是您要在一行中寻找的所有内容:
Event.joins(:user).where(:users => {:name => 'Bob'}, :events => {:start_at => Time.at(0)..Time.now })
您不能在 WHERE 子句 afiak 中使用 COUNT。您需要对结果进行分组并使用条件仅返回您想要的结果。
query = User.where(:name => 'Bob')
query = query.joins("LEFT JOIN (SELECT events.id FROM events WHERE events.start_at > '#{Time.now.to_s(:db)}') AS events ON events.user_id=users.id").group("users.id").where("events.id IS NULL")