Rails:从列中选择唯一值

问题描述 投票:0回答:14

我已经有了一个可行的解决方案,但我真的很想知道为什么这不起作用:

ratings = Model.select(:rating).uniq
ratings.each { |r| puts r.rating }

它选择但不打印唯一值,它打印所有值,包括重复项。它位于文档中:http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields

ruby-on-rails activerecord
14个回答
561
投票
Model.select(:rating)

其结果是

Model
对象的集合。不是简单的评级。而从
uniq
的角度来看,它们是完全不同的。你可以用这个:

Model.select(:rating).map(&:rating).uniq

或者这个(最有效):

Model.uniq.pluck(:rating)

轨道 5+

Model.distinct.pluck(:rating)

更新

显然,从 Rails 5.0.0.1 开始,它仅适用于“顶级”查询,如上所示。不适用于集合代理(例如“has_many”关系)。

Address.distinct.pluck(:city) # => ['Moscow']
user.addresses.distinct.pluck(:city) # => ['Moscow', 'Moscow', 'Moscow']

在这种情况下,在查询后进行去重

user.addresses.pluck(:city).uniq # => ['Moscow']

102
投票

如果您要使用

Model.select
,那么您不妨只使用
DISTINCT
,因为它只会返回唯一值。这更好,因为这意味着它返回更少的行,并且比返回大量行然后告诉 Rails 选择唯一值要稍微快一些。

Model.select('DISTINCT rating')

当然,前提是您的数据库能够理解

DISTINCT
关键字,而且大多数数据库都应该理解。


78
投票

这也有效。

Model.pluck("DISTINCT rating")

43
投票

如果您还想选择额外字段:

Model.select('DISTINCT ON (models.ratings) models.ratings, models.id').map { |m| [m.id, m.ratings] }

29
投票
Model.select(:rating).uniq

此代码自 rails 3.2 起作为“DISTINCT”(而不是 Array#uniq)工作

Rails 6 以上(?)应该是

Model.select(:rating).distinct

27
投票
Model.uniq.pluck(:rating)

# SELECT DISTINCT "models"."rating" FROM "models"

这样做的好处是不使用sql字符串,不实例化模型


15
投票
Model.select(:rating).distinct

6
投票

使用sql收集uniq列的另一种方法:

Model.group(:rating).pluck(:rating)

4
投票

如果我正要走的话:

当前查询

Model.select(:rating)

正在返回对象数组并且您已经编写了查询

Model.select(:rating).uniq

uniq 应用于对象数组,每个对象都有唯一的 id。 uniq 正在正确执行其工作,因为数组中的每个对象都是 uniq。

有很多方法可以选择不同的评级:

Model.select('distinct rating').map(&:rating)

Model.select('distinct rating').collect(&:rating)

Model.select(:rating).map(&:rating).uniq

Model.select(:name).collect(&:rating).uniq

还有一件事,第一个和第二个查询:通过 SQL 查询查找不同的数据。

这些查询将被视为“london”,而“london”同样意味着它将忽略空格,这就是为什么它会在查询结果中选择“london”一次。

第三次和第四次查询:

通过 SQL 查询查找数据,对于不同的数据应用 ruby uniq 方法。 这些查询将被视为“london”和“london”不同,这就是为什么它会在查询结果中选择“london”和“london”。

请更喜欢附图以方便理解,并查看“参观/等待 RFP”。

enter image description here


3
投票

如果有人正在寻找与 Mongoid 相同的东西,那就是

Model.distinct(:rating)

3
投票

一些答案没有考虑OP想要一个值数组

如果您的模型有数千条记录,其他答案则效果不佳

也就是说,我认为一个好的答案是:

    Model.uniq.select(:ratings).map(&:ratings)
    => "SELECT DISTINCT ratings FROM `models` " 

因为,首先生成一个模型数组(由于选择而尺寸减小),然后提取这些所选模型具有的唯一属性(评级)


2
投票

您可以使用以下 Gem:active_record_distinct_on

Model.distinct_on(:rating)

产生以下查询:

SELECT DISTINCT ON ( "models"."rating" ) "models".* FROM "models"

1
投票

在我的场景中,在按创建日期对它们进行排序、应用偏移量和限制后,我想要一个不同的

names
列表。基本上是
ORDER BY
DISTINCT ON

的组合

您需要做的就是将

DISTINCT ON
放入
pluck
方法中,如 follow

Model.order("name, created_at DESC").offset(0).limit(10).pluck(Arel.sql("DISTINCT ON (name) name"))

这将返回一组不同的

names


-2
投票
Model.pluck("DISTINCT column_name")
© www.soinside.com 2019 - 2024. All rights reserved.