【问题标题】:Rails: Postgresql where with multiple conditions with join (polymorphic)Rails:具有多个条件的 Postgresql 连接(多态)
【发布时间】:2012-05-28 12:24:27
【问题描述】:

大家好,这是我的代码:

class Tailor < ActiveRecord::Base
    has_many    :tailor_items
    has_many    :order_items

    [:collars, :sexes, :sleeves].each do |attribute|
        has_many    attribute, through: :tailor_items, source: :item, source_type: attribute.to_s.classify

    end
 end

class TailorItem < ActiveRecord::Base
  belongs_to        :tailor
  belongs_to        :item, polymorphic: true
end

class Collar < ActiveRecord::Base
end

我需要做的是: 对于给定的衬衫,我需要选择裁缝。衬衫可以有领子,男/女或某种类型的袖子。一些裁缝可以制作所有的衣领,但只能制作几个袖子,其他裁缝只能制作男性的东西,等等。 对于此示例,优先级无关紧要。我的想法是最终得到 1 个裁缝。

我试过这个:

tailors = Tailor.joins(:tailor_items).where("(item_id = ? and item_type = ?)",1,"Collar")
if tailors.count > 1
  tailors.where("(item_id = ? and item_type = ?)",2,"Sleeve")
  if tailors.count > 1
     # and so forth.
  end
end

但我从来没有得到回报。 如果我说:

Tailor.find(1).tailor_items 

我得到两个结果(为简单起见,sudo 代码)

<id: 1, item_type: "Collar"><id:2, item_type:"Sleeve"> 

第二个裁缝:

Tailor.find(2).tailor_items 

我得到两个结果(为简单起见,sudo 代码)

<id: 1, item_type: "Collar"><id:3, item_type:"Sleeve"> 

但是当我尝试将它们链接到查询中时它不起作用... 即使我把它们都放在一个地方:

Tailor.where("(item_id = 1 and item_type = 'Collar') and (item_id = 2 and item_type = 'Sleeve')")

我仍然得到 0 个结果。

Tailor.where("item_id = 1 and item_type = 'Collar'") returns: Tailor #1
Tailor.where("item_id = 2 and item_type = 'Sleeve'") returns: Tailor #1

但它们加在一起一无所获。

Tailor Load (0.0ms) SELECT "tailors".* FROM "tailors" INNER
JOIN "tailor_items" ON "tailor_items"."tailor_id" = "tailors"."id" WHERE ((tailo
r_items.item_id = 1 and tailor_items.item_type = 'Collar') and (tailor_items.ite
m_id = 2 and tailor_items.item_type = 'Sleeve'))

我很困惑..

感谢您的帮助。

我跑: 赢XP PostgreSQL 导轨 3.2.2

PS:在多态连接之后唯一缺少的就是一点 XML。 :P 否则它只是不够企业化..

编辑: 实现 Rob di Marcos 范围,我得到了这个 SQL:

SELECT "tailors".* FROM "tailors" WHERE 
(EXISTS(SELECT * FROM tailor_items WHERE tailor_items.item_id = 1 and tailor_items.item_type = 'Collar')) 
AND (exists(select * from tailor_items where tailor_items.item_id = 2 and tailor_items.item_type = 'Sleeve'))

这会返回 2 个裁缝,而不是只有 1 个可以同时做的裁缝(而裁缝 2 不能做袖子 #2)

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 postgresql activerecord join


    【解决方案1】:

    问题是 where 需要匹配两行。我通常会使用子查询来测试这一点。所以像

    Tailor.where("exists (select 'x' from tailor_items where 
             tailor_id = tailors.id and tailor_items.item_id = ? and 
             tailor_items.item_type=?)", 1, 'Collar').
           where("exists (select 'x' from tailor_items where 
             tailor_id = tailors.id and tailor_items.item_id = ? and 
             tailor_items.item_type=?)", 2, 'Sleeve')
    

    在此示例中,我为要查找的每件裁缝商品都有一个子查询。我可以轻松地将其作为 Tailor 的范围,例如:

    class Tailor
      # ....
      scope :with_item, lambda{ |item_id, item_type | 
          where("exists (select 'x' from tailor_items where 
         tailor_id = tailors.id and tailor_items.item_id = ? and 
         tailor_items.item_type=?)", item_id, item_type)
         }
    

    然后能够链接我的裁缝请求

    Tailor.with_item(1, 'Collar').with_item(2, 'Sleeve')
    

    【讨论】:

    • 好的,我确实让你的范围工作,最后有一个 ) 丢失。但现在的问题是它返回的结果太多。 Tailor1 有 Collar1、Sleeve1 和 Tailor2 有 Collar1、Sex1。如果我这样做: Tailor.with_item(1, "Collar").with_item(1, "Sex") 它返回 Tailor1 和 Tailor2。但我只想要裁缝 2。
    • 您能否查看日志并发布为选择生成的 SQL。
    • 我编辑了我的问题以包含 SQL。感谢您的帮助。
    • 哎呀,我看到了这个问题,您缺少“tailor_id = Tails.id”范围的一部分,该部分将存在的查询限制为仅与裁缝关联的项目。
    • 你今天赢得了互联网,我的朋友。非常感谢您的帮助:)
    猜你喜欢
    • 2018-12-06
    • 2011-12-19
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2012-01-08
    相关资源
    最近更新 更多