Rails:统计唯一记录,忽略某列
Rails: Count unique records, disregarding a certain column
我有以下table
| 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 |
------------------------
我想用只考虑 name
和 food
列的东西替换 .distinct
,而忽略价格,因此它会在之前删除重复的 Name/Food 对摸索。
或者,如果有更简单的方法来生成这个 UniqueFoods
专栏,那也会有所帮助。
你把 distinct
放在了错误的地方(这对你来说没有用,因为你后面有 group
)。
Person.select(:name, "count(distinct food) AS uniquefoods").group(:name)
您的原始解决方案的问题在于它的计算结果为 SELECT DISTINCT people.name, count(*) AS uniquefoods FROM people GROUP BY people.name
,它计算的是每个唯一人员的食物总数。我会避免使用 select 的公认解决方案,因为它会不必要地加载您的 Person 记录,而且作为 Rails 开发人员,您永远不会编写这种语法来解决此问题。以下是更符合最佳实践的查询示例:
按名称分组并对不同的食物进行计数计算将return将名称散列到不同的食物计数:
# Here are 2 examples
Person.group(:name).distinct(:food).count(:food)
Person.group(:name).count('distinct food')
=> { "Alice" => 2, "Bob" => 1, "Carol" => 1 }
这是执行计数计算的首选解决方案,并且可以在恒定时间内很好地访问结果,因为它 return 将它们作为散列。您可以传递 group
一个或多个值以用于键,该值将是您 count
编辑的任何值。对多列进行分组时,哈希键是包含两个分组值的数组。
或者,您可以使用 pluck
到 return 一个或多个列中所需值的数组:
# 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
具有性能优势,但最常见的是您会看到它用于 select 来自单个列的值。
Rails 查询方式一般来说真的很灵活。如果您不熟悉它,请查看 Rails AR 查询指南:https://guides.rubyonrails.org/active_record_querying.html
我有以下table
| 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 |
------------------------
我想用只考虑 name
和 food
列的东西替换 .distinct
,而忽略价格,因此它会在之前删除重复的 Name/Food 对摸索。
或者,如果有更简单的方法来生成这个 UniqueFoods
专栏,那也会有所帮助。
你把 distinct
放在了错误的地方(这对你来说没有用,因为你后面有 group
)。
Person.select(:name, "count(distinct food) AS uniquefoods").group(:name)
您的原始解决方案的问题在于它的计算结果为 SELECT DISTINCT people.name, count(*) AS uniquefoods FROM people GROUP BY people.name
,它计算的是每个唯一人员的食物总数。我会避免使用 select 的公认解决方案,因为它会不必要地加载您的 Person 记录,而且作为 Rails 开发人员,您永远不会编写这种语法来解决此问题。以下是更符合最佳实践的查询示例:
按名称分组并对不同的食物进行计数计算将return将名称散列到不同的食物计数:
# Here are 2 examples
Person.group(:name).distinct(:food).count(:food)
Person.group(:name).count('distinct food')
=> { "Alice" => 2, "Bob" => 1, "Carol" => 1 }
这是执行计数计算的首选解决方案,并且可以在恒定时间内很好地访问结果,因为它 return 将它们作为散列。您可以传递 group
一个或多个值以用于键,该值将是您 count
编辑的任何值。对多列进行分组时,哈希键是包含两个分组值的数组。
或者,您可以使用 pluck
到 return 一个或多个列中所需值的数组:
# 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
具有性能优势,但最常见的是您会看到它用于 select 来自单个列的值。
Rails 查询方式一般来说真的很灵活。如果您不熟悉它,请查看 Rails AR 查询指南:https://guides.rubyonrails.org/active_record_querying.html