Rails:从一个列中选择唯一的值

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

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

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

256825 次浏览
Model.select(:rating)

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

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

或者这样(最有效):

Model.uniq.pluck(:rating)

Rails 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']
Model.select(:rating).uniq

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

如果你打算使用Model.select,那么你最好只使用DISTINCT,因为它只会返回唯一的值。这样更好,因为这意味着它返回更少的行,并且应该比返回一些行然后告诉Rails选择惟一值略快。

Model.select('DISTINCT rating')

当然,这是在你的数据库理解DISTINCT关键字的前提下,而且大多数人都应该理解。

这也有用。

Model.pluck("DISTINCT rating")

如果我要直接走,那么:

当前查询

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

Model.uniq.pluck(:rating)


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

这具有不使用sql字符串和不实例化模型的优点

Model.select(:rating).distinct

如果有人想在蒙古人身上找到同样的东西,那就是

Model.distinct(:rating)

有些答案没有考虑到OP需要值数组

如果您的Model有数千条记录,其他答案就不能很好地工作

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

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

因为,首先生成一个Model数组(由于选择而减小了大小),然后提取那些所选模型的唯一属性(评级)

如果你还想选择额外的字段:

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

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

Model.group(:rating).pluck(:rating)
Model.pluck("DISTINCT column_name")

你可以使用下面的Gem: active_record_distinct_on

Model.distinct_on(:rating)

产生以下查询:

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

在我的场景中,我想要一个不同的names列表,在按创建日期排序后,应用offset和limit。基本上是ORDER BYDISTINCT ON的组合

你所需要做的就是将DISTINCT ON放入pluck方法中,就像下面这样

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

这将返回一个不同names的数组。