使用uniq时,Activerecord查询返回双精度数

时间:2015-03-14 13:44:46

标签: sql activerecord

我正在运行以下查询,目的是返回一组唯一的customer个对象:

Customer.joins(:projects).select('customers.*, projects.finish_date').where("projects.closed = false").uniq

但是,如果客户有多个项目处于活动状态(例如,closed = true),则此代码将生成重复项。如果我从projects.finish_date子句中删除select,则此查询将按预期工作。但是,我需要在那里能够对该列进行排序。

如何让此查询返回一组唯一的客户?

1 个答案:

答案 0 :(得分:0)

  

如何让此查询返回一组唯一的客户?

这并不完全有意义,可能不是你想要的。

问题是您正在加入projects表,此时同一客户可能有多行具有不同的项目finish_date。这些行 唯一,将作为多个唯一Customer个对象返回,每个对象的finish_date不同。

如果您只想要其中之一,Rails如何确定哪一个?如果只有一个客户对象返回一个finish_date,如果该客户真的有10个项目,每个项目都有不同的finish_date,那么这不是问题吗?

相反,你可能想要这样的东西:

customers = Customer.joins(:projects).select('customers.*, projects.finish_date').where("projects.closed = false").uniq

customers.group_by(&:id)

将您的所有同一客户组合在一起。

或者,你可能想要:

projects = Project.where(closed: false).includes(:user)
users = projects.map(&:user).uniq

在任何一种情况下,您都是从所有用户项目联接的超集中生成一组唯一的用户。


RE您的意见:

如果您想获得包含最新关联项目的客户列表,可以在where中使用子查询:

select customers.*, projects.finish_date from customers
  inner join projects on projects.customer_id = customers.id
  where projects.id = (
    select id from projects
      where customer.id = project.customer_id
        and closed = false
      order by finish_date desc
      limit 1
  )

您可以使用ActiveRecord通过在where中嵌入子查询来表达这一点:

Customer.joins(:projects)
  .select('customers.*, projects.finish_date as finish_date')
  .where('select id from projects where customer.id = project.customer_id and closed = false order by finish_date desc limit 1')

我不知道这会对你有什么影响,但我怀疑是不好的。

在尝试使用SQL进行优化之前,我总是坚持使用简单的includes和in-Ruby过滤器。