记录与相关记录的组合

时间:2018-01-15 08:45:22

标签: ruby-on-rails activerecord

我有一个模型Product,其中有许多property_products关联,我想要获取包含两个或更多property_products的所有产品。

我试过了:

Product.joins(:property_products)
  .where("(property_products.property_id = '2' AND property_products.value= '195')
      AND (property_products.property_id = '3' AND property_products.value = '65')"
  )

但它不会返回任何记录。

Product Load (1.5ms)  SELECT "products".* FROM "products" INNER JOIN "property_products" ON "property_products"."product_id" = "products"."id" WHERE ((property_products.property_id = '2' AND property_products.value= '195') AND (property_products.property_id = '3' AND property_products.value = '65'))
=> #<ActiveRecord::Relation []>

我也尝试过:

Product.joins(:property_products)
  .where("property_products.property_id = '2' AND property_products.value = '195'")
  .where("property_products.property_id = '3' AND property_products.value = '65'")

但结果是一样的。

3 个答案:

答案 0 :(得分:1)

您的查询永远不会匹配任何记录。您where条款的含义如下:

  

每一个 property_product必须满足以下4个条件:

     
      
  • 有property_id = 2 AND property_id = 3(在单个记录中永远不会发生)
  •   
  • 有值= 195 AND值= 65(这也不会发生在单个记录上)
  •   

相反,您希望查询条件类似于:

  

必须为每个产品填写以下条件:

     
      
  • 必须有关联的property_product,其product_id = 2 AND值= 195

  •   
  • 并且必须另一个关联property_product,其product_id = 3 AND值= 65

  •   

鉴于您在评论中提供的事实......

  

&#34;产品不能有多个property_products,其中一个property_id

...这是使用纯SQL执行此操作的一种方法:

product_ids = ActiveRecord::Base.connection.execute('
                select product_id, count(product_id)
                from property_products
                where (property_id = 2 AND value = 195)
                OR (property_id = 3 AND value = 65)
                GROUP BY product_id
                HAVING count(product_id) = 2')
              .map { |i| i['product_id'] }

products = Product.where(id: product_ids)

请注意,HAVING count(product_id) = 2纯粹是因为您与2 property_products匹配。更改条件时更新号码。

当然,这不是Rails中最优雅的解决方案,可能会有更好的解决方案。但这只是一个快速的&amp;肮脏的解决方案。

答案 1 :(得分:0)

您的查询

Product.joins(:property_products).where("
  (property_products.property_id = '2' AND property_products.value= '195')
  AND
  (property_products.property_id = '3' AND property_products.value = '65')
")

永远不会匹配任何记录。也许,你将OR拼错到AND

Product.joins(:property_products).where("
  (property_products.property_id = '2' AND property_products.value= '195')
  OR
  (property_products.property_id = '3' AND property_products.value = '65')
")

答案 2 :(得分:0)

Altough Tamer Slash的解决方案有效,我找到了更优雅的解决方案:

Product.joins('join property_products as p1 on products.id=p1.product_id')
.joins('join property_products as p2 on products.id=p2.product_id')
.where('p1.value = 195 AND p1.property_id = 2')
.where('p2.value = 65 AND p2.property_id = 3')