【问题标题】:ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column for `where` query when using includesActiveRecord::StatementInvalid: Mysql2::Error: Unknown column for `where` query when using includes
【发布时间】:2019-02-18 07:42:00
【问题描述】:

我有以下关联:

mobile_application.rb

has_many :events

事件.rb

belongs_to :mobile_application

以下运行正常:

MobileApplication.includes(:events)
#=> MobileApplication Load (1.6ms)  SELECT `mobile_applications`.* FROM `mobile_applications`  ORDER BY created_at desc
#   Event Load (1.3ms)  SELECT `events`.* FROM `events` WHERE `events`.`mobile_application_id` IN (746, 745, 744, ....

但是当我尝试以下方法时,

MobileApplication.includes(:events).where("events.expiry_date >= ?", Time.zone.now)

它会抛出一个错误:

MobileApplication Load (1.2ms)  SELECT `mobile_applications`.* FROM `mobile_applications` WHERE (events.expiry_date >= '2019-02-18 07:34:40.738517')  ORDER BY created_at desc
Mysql2::Error: Unknown column 'events.expiry_date' in 'where clause': SELECT `mobile_applications`.* FROM `mobile_applications` WHERE (events.expiry_date >= '2019-02-18 07:34:40.738517')  ORDER BY created_at desc
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'events.expiry_date' in 'where clause': SELECT `mobile_applications`.* FROM `mobile_applications` WHERE (events.expiry_date >= '2019-02-18 07:34:40.738517')  ORDER BY created_at desc

更新

请建议我如何过滤它。使用 references 也会引发以下错误,并且与 Marek Lipka 提供的答案相同,

ActiveRecord::StatementInvalid: Mysql2::Error: Column 'created_at' in 
order clause is ambiguous: SELECT `mobile_applications`.`id` AS t0_r0, 
`mobile_applications`.`name` AS t0_r1, ...

我猜这是由于模型中存在的default_scope 创建的列不明确,以便按两个关联表中都存在的created_at 对其进行排序。

【问题讨论】:

  • 好像和引用无关,events表没有expiry_date列。你运行迁移了吗?
  • @Sid 是的,我得到了同样的参考错误,这是我从 Marek Lipka 提供的解决方案中得到的。更新问题!

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord


【解决方案1】:

默认情况下,includes 不执行 left join,而是执行两个单独的 DB 查询。您可以使用eager_load 强制left join,如下所示:

MobileApplication.eager_load(:events).where('events.expiry_date >= ?', Time.zone.now)

或者,如果您实际上不需要预先加载(我不知道),您可以简单地使用joins

MobileApplication.joins(:events).where('events.expiry_date >= ?', Time.zone.now)

关于使用referenceseager_load 的错误:您显然尝试在某处通过created_at 进行订购(尽管您没有在问题中包含此内容),例如:

order('created_at DESC')

所以,很明显,DB 不知道您对joins 有什么表,因为mobile_applicationsevents 中都有created_at 列。所以你需要指定“目标”表,比如:

order('mobile_applications.created_at DESC')

【讨论】:

  • 是的,我需要将其过滤掉(不需要进一步的关联记录),所以连接有效,我忘记了,只尝试了includes
  • eager_load 尝试过,但我在includesreferences 中遇到了同样的错误,我在问题更新中添加的内容,请在此处查看并评论可能的原因。
  • @ray 使用referenceseager_load 时会不会出现同样的错误?数据库查询是什么样的?
  • joins 现在对我来说已经足够了,但我很好奇我得到的更新有问题。这我以前也遇到过includes - references 用于undefined column for table 错误但后来得到错误列歧义错误 for order('column_name') 所以我曾经按顺序提供它(table_name.column_name)
  • @ray 我编辑了我的答案来解决这个问题,请检查。
【解决方案2】:

从 rails 4.x 开始,您必须添加关键字 references:

MobileApplication.includes(:events).references(:events).where("events.expiry_date >= ?", Time.zone.now)

【讨论】:

  • includesreferences 我使用了 created_at 的抛出列歧义错误,我猜是 default_scope 触发了 order 查询。也许joins 为我工作只是为了过滤它。
猜你喜欢
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 2018-08-05
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多