[英]ActiveRecord query based on multiple objects via has_many relationship
[英]ActiveRecord has_many with multiple conditions
我试图通过检查几个对象的关系来查找对象。
Loan.joins(:credit_memo_attributes)
.where(credit_memo_attributes: {name: 'pr2_gtx1_y', value: '2014'})
.where(credit_memo_attributes: {name: 'pr1_gtx1_y', value: '2013'})
.where(credit_memo_attributes: {name: 'tx1_y', value: '2014'})
调用to_sql
会得到:
"SELECT `loans`.* FROM `loans` INNER JOIN `credit_memo_attributes`
ON `credit_memo_attributes`.`loan_id` = `loans`.`id`
WHERE `credit_memo_attributes`.`name` = 'pr2_gtx1_y' AND `credit_memo_attributes`.`value` = '2014'
AND `credit_memo_attributes`.`name` = 'pr1_gtx1_y' AND `credit_memo_attributes`.`value` = '2013'
AND `credit_memo_attributes`.`name` = 'tx1_y' AND `credit_memo_attributes`.`value` = '2014'"
因此,我正在检查具有所有这些属性的credit_memo_attributes的贷款。 我知道我们20,000笔贷款中至少有1笔符合此条件,但是此查询返回的是空集。 如果我只使用where
子句中的1个,它会返回几个,正如我期望的那样,但是一旦我再添加1个,它就为空。
知道我哪里出错了吗?
基于评论,我相信您希望您的条件中包含多个联接。 您可以这样做:
attr_1 = {name: 'pr2_gtx1_y', value: '2014'}
attr_2 = {name: 'pr1_gtx1_y', value: '2013'}
attr_3 = {name: 'tx1_y', value: '2014'}
Loan.something_cool(attr_1, attr_2, attr_3)
class Loan < ActiveRecord::Base
...
def self.something_cool(attr_1, attr_2, attr_3)
joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma1 ON cma1.loan_id = loans.id AND cma1.name = :name AND cma1.value = :value", attr_1]))
.joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma2 ON cma2.loan_id = loans.id AND cma2.name = :name AND cma2.value = :value", attr_2]))
.joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma3 ON cma3.loan_id = loans.id AND cma3.name = :name AND cma3.value = :value", attr_3]))
end
如果查看生成的SQL(包括在问题中,谢谢),您将看到所有这些条件都被“与”在一起。 没有名称为“ pr2_gtx1_y”且名称为“ pr1_gtx1_y”(依此类推)的行。 因此,您得到的结果是我期望的(无行)。
您可以将所有名称和值放入ID和Year之类的数组中,然后将其传递到where子句中。 Active Record将查询数组中的所有值。
Loan.joins(:credit_memo_attributes)
.where(credit_memo_attributes: {name: ids, value: years})
就我个人而言,我仍在学习活动记录,在这种情况下,我认为活动记录不支持多个where子句。
请注意, SQL
版本如何返回您的代码:它使用AND
将需求连接在一起。
"SELECT `loans`.* FROM `loans` INNER JOIN `credit_memo_attributes`
ON `credit_memo_attributes`.`loan_id` = `loans`.`id`
WHERE `credit_memo_attributes`.`name` = 'pr2_gtx1_y' AND `credit_memo_attributes`.`value` = '2014'
AND `credit_memo_attributes`.`name` = 'pr1_gtx1_y' AND `credit_memo_attributes`.`value` = '2013'
AND `credit_memo_attributes`.`name` = 'tx1_y' AND `credit_memo_attributes`.`value` = '2014'"
现在,这几乎是不可能的。 Object.name
永远不能都是pr2_gtx1_y
, pr1_gtx1_y
和tx1_y
。 value
属性也是如此。
在这里,您需要的是OR
AND
。
为此,请尝试将查询更改为以下内容:
Loan.joins(:credit_memo_attributes)
.where(
"credit_memo_attributes.name = ? and credit_memo_attributes.value = ?
OR credit_memo_attributes.names = ? and credit_memo_attributes.value = ?
OR credit_memo_attributes.name = ? and credit_memo_attributes.value = ?",
'pr2_gtx1_y', '2014',
'pr1_gtx1_y', '2013',
'tx1_y', '2014'
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.