Rails:计算唯一记录,不考虑某一列

时间:2021-06-24 01:26:01

标签: ruby-on-rails activerecord

我有下表

| Name   | Food  | Price |
--------------------------
| Alice  | Pizza | 5     |
| Alice  | Pizza | 10    |
| Alice  | Salad | 5     |
| Bob    | Soup  | 20    |
| Bob    | Soup  | 15    |
| Carol  | Pork  | 10    |
--------------------------

我想找到类似的东西

------------------------
| Name   | UniqueFoods |
------------------------
| Alice  | 2           | # Pizza and Salad
| Bob    | 1           | # Has only had soup, despite having it twice
| Carol  | 1           |
------------------------

我尝试了各种类似的东西

Person.select(:name, "count(*) AS uniquefoods").distinct.group(:name)

然而,这会产生

------------------------
| Name   | UniqueFoods |
------------------------
| Alice  | 3           | # incorrect
| Bob    | 2           | # incorrect
| Carol  | 1           |
------------------------

我想将 .distinct 替换为仅考虑 namefood 列且不考虑价格的内容,因此它会在摸索之前删除重复的 Name/Food 对。

或者,如果有更简单的方法来生成此 UniqueFoods 列,那也会有帮助。

2 个答案:

答案 0 :(得分:1)

您将 distinct 放在错误的位置(在您的情况下这是无用的,因为它后面有 group)。

Person.select(:name, "count(distinct food) AS uniquefoods").group(:name)

答案 1 :(得分:1)

您的原始解决方案的问题在于它的计算结果为 SELECT DISTINCT people.name, count(*) AS uniquefoods FROM people GROUP BY people.name,即计算每个唯一人的食物总数。我会避免使用 select 的公认解决方案,因为它不必要地加载了您的 Person 记录,并且您永远不会编写它的语法来解决这个问题,作为 Rails 开发人员。以下是更符合最佳做法的查询示例:

按名称分组并对不同的食物执行计数计算将返回不同食物计数的名称散列:

# Here are 2 examples
Person.group(:name).distinct(:food).count(:food)
Person.group(:name).count('distinct food')
=> { "Alice" => 2, "Bob" => 1, "Carol" => 1 }

这是执行计数计算的首选解决方案,并且可以在恒定时间内很好地访问结果,因为它将它们作为散列返回。您可以传递 group 一个或多个值以用作键,并且该值将是您count设置的任何值。对多列执行分组时,哈希键是包含两个分组值的数组。

或者,您可以使用 pluck 从一列或多列返回您想要的值的数组:

# Plucking 2+ columns yields a 2-dimensional array simulating rows
Person.group(:name).pluck(:name, 'count(distinct food)')
=> [["Alice", 2], ["Bob", 1], ["Carol", 1]]

# Plucking 1 column yields a 1-dimensional array simulating a column
Person.distinct(:name).pluck(:name)
=> ["Alice", "Bob", "Carol"]

Pluck 非常方便,并且比 select 具有性能优势,但最常见的是您会看到它用于从单个列中选择值。

Rails 查询方法通常非常灵活。如果您不熟悉它,请查看有关 AR 查询的 Rails 指南:https://guides.rubyonrails.org/active_record_querying.html