Sql Rails 3:ActiveRecord查询with:includes仅返回包含表中具有相关值的结果?
我有一个模型(一个Sql Rails 3:ActiveRecord查询with:includes仅返回包含表中具有相关值的结果?,sql,ruby-on-rails-3,activerecord,Sql,Ruby On Rails 3,Activerecord,我有一个模型(一个功能),可以有许多资产。这些资产各有一个发行日期。我正在努力寻找一个简单的ActiveRecord查询,用明天的发行日期查找所有功能及其资产,而不管是否有资产——最好用一个查询 这是我现在的问题 Feature.includes(:assets).where(:assets => { :issue_date => Date.tomorrow }) 不幸的是,这只返回具有资产的功能,其发行日期为明天。更奇怪的是,生成的SQL看起来是这样的(明天显然是19号) 这里不
功能
),可以有许多资产
。这些资产
各有一个发行日期
。我正在努力寻找一个简单的ActiveRecord查询,用明天的发行日期查找所有功能及其资产,而不管是否有资产——最好用一个查询
这是我现在的问题
Feature.includes(:assets).where(:assets => { :issue_date => Date.tomorrow })
不幸的是,这只返回具有资产的功能,其发行日期为明天。更奇怪的是,生成的SQL看起来是这样的(明天显然是19号)
这里不应该有一个左连接吗?这正是我想要的。使用连接
而不是包含
会执行内部连接
,但这不是我想要的。奇怪的是,我似乎得到了一种内部连接类型的行为。当我运行上面的includes
查询时,吐出的实际SQL如下所示
SELECT `features`.`id` AS t0_r0, `features`.`property_id` AS t0_r1,
// every other column from features truncated for sanity
`assets`.`feature_id` AS t1_r1, `assets`.`asset_type` AS t1_r2,
// all other asset columns truncated for sanity
FROM `features`
LEFT OUTER JOIN `assets` ON `assets`.`feature_id` = `features`.`id`
WHERE `assets`.`issue_date` = '2011-08-19'
哪个看起来像它应该正常工作,但它没有。我只得到功能
,这些功能具有资产
,发行日期为明天。知道我做错了什么吗
我试过更老的,Rails v2的方法
Feature.find(:all,
:include => :assets,
:conditions => ['assets.issue_date = ?', Date.tomorrow])
这给了我同样的结果。有一个功能
我知道明天没有任何资产
,它不在列表中
我也四处探索,发现了类似的问题,但我似乎找不到一个能解释我所看到的相反行为的问题
编辑:我太接近了。这将获得所有功能
对象
Feature.joins("LEFT OUTER JOIN assets on assets.feature_id = feature.id AND asset.issue_date = #{Date.tomorrow}")
但是,它确实而不是,将匹配的资产
捆绑到对象中。使用feature
作为查询中的返回项,feature.assets
再次调用数据库,这是我不想要的。我希望feature.assets
只返回我在该左外部联接调用中指定的那些。我还需要对我的查询执行什么操作?您是否尝试过:
Feature.joins( :assets ).where( :issue_date => Date.tomorrow );
这里的指南建议使用includes方法来减少辅助表上的查询数量,而不是以您尝试的方式连接两个表
您必须自己为外部联接指定SQL,而联接
方法仅使用内部联接
Feature.joins("LEFT OUTER JOIN assets ON assets.feature_id = features.id").
where(:assets => {:issue_date => Date.tomorrow})
我以为这能满足我的需要,但事实并非如此。调用feature.assets
(将feature
作为我查询中返回的项目)执行另一个查询,以查找与该功能相关的所有资产
Feature.joins("LEFT OUTER JOIN assets on assets.feature_id = feature.id AND asset.issue_date = #{Date.tomorrow}")
以下是有效的方法。看起来也有点干净。我的功能
模型已经有了设置了很多:资产。我已经与建立了另一个关联,它指向资产,但有一个条件。然后,当我请求功能.all
或功能.name\u范围
时,我可以指定.includes(:tomorrows\u资产)
。赢家,赢家,鸡肉晚餐
has_many :tomorrows_assets,
:class_name => "Asset",
:readonly => true,
:conditions => "issue_date = '#{Date.tomorrow.to_s}'"
我可以成功地查询功能
并获得所需的内容,前提是它符合指定的条件(我已经设置了:readonly
,因为我知道我永远不想像这样编辑资产
)。这是一个IRB会议,展示了魔术
features = Feature.includes(:tomorrows_assets)
feature1 = features.find_all{ |f| f.name == 'This Feature Has Assets' }.first
feature1.tomorrows_assets
=> [#<Asset id:1>, #<Asset id:2>]
feature2 = features.find_all{ |f| f.name == 'This One Does Not' }.first
feature2.tomorrows_assets
=> []
features=Feature.includes(:明天的资源)
feature1=features.find_all{| f | f.name=='此功能具有资产'}。首先
功能1.tomorrows_资产
=> [#, #]
feature2=features.find_all{| f | f.name=='这一个没有'}。首先
功能2.tomorrows_资产
=> []
而且只需要两个SQL查询。我遇到了一个非常类似的问题,并使用以下查询设法解决了它
Feature.includes(:assets).where('asset.id IS NULL OR asset.issue_date = ?', Date.tomorrow)
这将加载所有功能,无论它是否有任何资源。调用feature.asset将返回一个资产数组(如果可用),而无需运行另一个查询
希望这对别人有帮助 如果issue_date是asset表中的一个字段,那么您希望对特定issue_date的查询如何返回没有任何资产的功能?如果我的帖子在这方面不清楚,我很抱歉。我想要一份特定日期所有功能
以及资产
的列表,如果这些资产
存在;否则,只需使用功能
。哦,对不起,我理解了,您确实解释了,但我想我在阅读rails生成的查询时迷路了。issue\u date是对外部联接的查询,而不是对结果集的查询。使用您的查询时,会抱怨资产类型
不是功能
的一部分,因此我重新编写了最后一个where
子句,该子句将围绕资产
的哈希进行包装(就像我查询的最后一部分)。运行它会执行一个内部联接
,得到与上面相同的结果。似乎我需要的是一种直接指定与外部联接
匹配的条件的方法。此查询还排除了没有任何与资产
条件匹配的功能
。如果我可以在joins
字符串中指定问题日期条件,会怎么样?我可以这样做吗?
Feature.includes(:assets).where('asset.id IS NULL OR asset.issue_date = ?', Date.tomorrow)