繁体   English   中英

ActiveRecord has_many具有多个条件

[英]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_ypr1_gtx1_ytx1_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM