Rails:如何从列中获取唯一值

94

如何从表格列中获取唯一值?例如,我有这个Products表:

ID NAME CATEGORY
1 name1 1st_cat
2 name2 2nd_cat
3 name3 1st_cat

我想要获取仅限于2个值 - 1st_cat 和 2nd_cat:

<%Products.each do |p|%>
<%=p.category%>
<%end%>

你可以使用 Product.group("category_id") 进行分组。 - Neelesh
2
以下是所有可能的方法 - 需要注意的是,Products.uniq.pluck(:category) 是最有效的方法。 - Yo Ludke
3
只是一个想法;如果你的模型名称是复数形式,那么从Rails的角度来看,你做错了。 - rcd
8个回答

204

还有两种方式:

Product.select(:category).map(&:category).uniq # Ruby does the work

Product.uniq.pluck(:category) # DB does the work (superior)

对于Rails >= 5.1,请使用:

Product.distinct.pluck(:category) # DB does the work (superior)

...由于 Relation#uniq 已被弃用


2
我正好在找这个: Products.pluck(:category).uniq太棒了!+1 :) - K M Rakibul Islam
8
这将把所有产品拉入一个 Ruby 数组中,而不是在数据库中完成工作。 - superluminary
1
@superluminary是将所有产品都放入Ruby数组中,而不是让数据库来完成工作。这是推荐的做法吗? - 8bithero
13
User.uniq.pluck(:source) 会产生 SELECT DISTINCT "users"."source" FROM "users" 的查询语句,因此我认为它不会将所有记录加载到 Ruby 数组中。 - Rafael Oliveira
4
对于 Rails >= 5.1,请使用 Products.distinct.pluck(:category) - davegson
显示剩余5条评论

27

我自己也是Rails的新手(现在只是通过教程来学习)我谷歌了一下。 - ThatOtherPerson
仅适用于您只想要1列,其他列未被选中。 - srghma

13

这将在数据库服务器上完成所有的工作,结果是一个简单的数组。

<% Product.distinct(:category).pluck(:category).each do |category|
    <%= category %>
<% end %>

Rails 会生成可以在任何数据库上运行的 SQL(例如 Postgres、MySQL 等)。

SELECT DISTINCT "products"."category" FROM "products"

9

我建议使用Products.all.distinct.pluck(:category),因为自Rails 5以来,uniq已经被弃用,并且在Rails 5.1中将被移除。


6
尝试在Rails控制台中执行以下命令:
Product.group(:category)

Product.group(:category).each { |p| p.name }

5
只有在MySql数据库上才能正常运行(可能SQLite也可以,但在Postgres或MSSQL上绝对不太好)。 - jamesc
适用于sqlite。 - Geoffrey H
你需要使用 Product.select(:category).group(:category) 才能在 Postgresql(我猜 MSSQL 也是如此)上使其正常工作。 - Ben Trewern

4

对于PostgreSQL

<% Product.select("DISTINCT ON (category) *").each do |category|
    <%= category %>
    <%= name %>
<% end %>

更新

更好的

<% Product.select(%(DISTINCT ON (category) "#{Product.table_name}".*)).each do |category|
    <%= category %>
    <%= name %>
<% end %>

因为在进行 joins 时可能会返回错误的列(例如,返回来自连接表的 id 列,但不包括 products 列)


投票支持,因为当您需要整个活动记录关系而不是已选择的值数组时,此解决方案对我很有用。 - Arth Thakkar

1
如果您或任何人想要从一个表中(如产品)基于属性的不同特征获取两个或更多属性,只有这个解决方案可以帮助您进行Rails >= 5.1
distinct_products = Product.select("DISTINCT ON (category) *")

# it's an active record relation class.
> distinct_products.class
=> Product::ActiveRecord_Relation
注意:不要在distinct_products上使用.pluck()。这将重新从products表中进行选择,导致去重功能失效。

0

我需要获取唯一的输出,尝试使用“uniq”方法但没有成功。尝试了这里发布的几个解决方案,但都没有成功。我正在使用Devise,它使我可以访问current_user方法,并且正在使用两个表格,其中一个是连接(一个项目有多个:things)。

最终,这个解决方案对我起作用:

@current_user.things.select(:item_fk).distinct.each do |thing|
 <%= thing.item.attribute %>
<% end %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接