复杂的导轨找到订购

时间:2010-08-03 10:43:00

标签: sql ruby-on-rails activerecord

我正在尝试查找按照其房屋名称和客户的姓氏订购结果。

Customer.find(:all, 
    :conditions =>['customers.id IN (?)', intersection], 
    :joins => 'JOIN histories ON histories.customer_id = customers.id
     JOIN houses ON histories.house_id = houses.id',
    :order => "houses.name ASC, customers.last_name ASC",
    :select => "customers.*, histories.job_title, houses.name"
)

我的问题是这将返回与每位客户相关的所有历史记录。

如果我添加AND histories.finish_date IS NULL 这将阻止返回所选客户的所有历史记录,但也会阻止交叉路口中没有历史记录或者设置完成的finish_date的客户退回。

基本上我需要交叉路口的每个客户都返回一次当前的房屋名称(如果有的话),然后按他们的房屋名称和他们的姓氏排序。

有没有办法做到这一点?

这是一个例子

客户

id  last_name
1     franks
2     doors
3     greens

历史

id    finish_date      house_id     customer_id
1        NULL             1             1
2        NULL             2             2
3        11/03/10         2             1
4        22/04/09         1             2

NULL =当前的房子

房屋

id name
1    a
2    b

结果

交叉点= 1,2,3

last_name       house     
franks            a
doors             b
greens            NULL

由于

2 个答案:

答案 0 :(得分:0)

IMO在Rails而不是数据库中进行排序逻辑更简单:

customers = Customer.find(:all, :conditions => { :id  => intersection }, :include => [ { :histories => :houses } ])

customers.sort_by { |c| c.last_name }
customers.sort_by do |c|
  current_house = c.histories.find_by_finish_date(nil) # Returns nil if no matching record found
  if current_house
    current_house.name
  else
    ''
  end
end

<强>说明

  • :条件可以采用哈希值{:column_name =&gt; array}转换为IN where-condition
  • :如果存在相应的关联,则包括表的预加载(eager loading)。换句话说::: join创建INNER JOIN,而:include创建LEFT JOINs。在这里,我们将离开连接历史,并再次离开连接房屋。您可以省略:include标记,在这种情况下,每次访问历史记录或房屋时,rails都会执行新查询。
  • sort_by允许定义自定义排序条件。
  • find_by_finish_date是rails的魔法之一;它相当于h.find(:conditions => {:finish_date => nil })
  • 如何输出:只需在视图中输出所有这些内容。如果他没有历史,那么customer.histories就是一个空数组。

答案 1 :(得分:0)

我认为你需要使用外连接。

例如,这应该有效:

Customer.find(:all, 
  :conditions =>['customers.id IN (?) and histories.finish_date is null', intersection], 
  :joins => 'LEFT OUTER JOIN histories ON histories.customer_id = customers.id
    LEFT OUTER JOIN houses ON histories.house_id = houses.id',
  :order => "houses.name ASC, customers.last_name ASC",
  :select => "customers.*, histories.job_title, houses.name"
)

如果您在“客户”和“历史记录”之间以及“历史记录”和“众议院”之间建立了关联,则应该能够:include => [:histories => :house]而不是:joins选项。

唯一的另一件事是没有房子的客户将首先出现在列表中,因为订单中的NULL早于非NULL值。您可能想尝试这样的订单选项:

:order => 'isnull(houses.name), houses.name, customers.last_name'

实现您指定的目标。