SQL和Rails复杂查询

时间:2015-04-21 18:04:34

标签: sql ruby-on-rails

我正在构建一个Rails应用程序来管理服务公司的日程安排。

对于这个问题的范围,模型结构是:

  

客户有很多合同

     

合同有很多服务

     

工人有很多服务

在我的查询中,我有一个工人和一个客户,我需要制作一个

  

@contracts relationship

匹配所有与客户和工作人员共同的合同。

我已经尝试了很多方法,但是如果我通过select {}和循环递归地生成@contracts列表,我获得的数组不是ActiveRecord而且它不能在rails app中使用(例如在erb)。

我被卡住了:/

2 个答案:

答案 0 :(得分:1)

假设您有正确的has_manybelongs_to关系设置,您的查询可能会是这样的:

Contract.joins(services: :worker)
        .where(services: {worker_id: target_worker_id})
        .where(contracts: {client_id: target_client_id}).uniq

其中target_worker_idtarget_client_id是您希望过滤的工作人员和客户。

此查询会将contracts加入services表(因为您说"合同有许多服务"),它也将services表连接到{ {1}}表(因为你说"工人有很多服务")。简而言之,workers似乎是一个连接表,是多对多关系的结果,因此是连接子句。

编辑:注意services,这是确保仅加载不同.uniq个对象所必需的。否则,正如您所经历的那样,由Contract方法引起的内部联接将基本上创建一个重复的集合。

如果我误解了任何内容,或者您​​对此答案有其他疑问,请与我联系。

快速注意:你写了我获得了一个不是ActiveRecord的数组,它不能在rails应用程序中使用(例如在erb中)。我不完全清楚你是什么是的,但在控制器中创建的任何实例变量都可以在ERB中使用;它不需要是一个活动的记录对象。如上所述,我不确定这是不是你的意思。

答案 1 :(得分:0)

class Client < ActiveRecord::Base
  has_many :conctracts, inverse_of: client, dependent: :destroy
end

class Contract < ActiveRecord::Base
  has_many :services
end

class Worker < ActiveRecord::Base
  has_many :services

end

class Service < ActiveRecord::Base
  belongs_to :worker
  belongs_to :contract

  has_many :clients, through: contract

  scope :workers, ->(*w) {
    where(worker_id: w.flatten.compact.uniq)
  }

  scope :contracts, ->(*c) {
    where(contract_id: c.flatten.compact.uniq)
  }
end

workers = Worker.all

clients = Client.join(contracts: {services: worker}).merge(Service.workers(workers))