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)