如何使用 arel/关系代数获取不同的值
Posted
技术标签:
【中文标题】如何使用 arel/关系代数获取不同的值【英文标题】:How to fetch distinct values with arel/relational algebra 【发布时间】:2011-03-09 08:30:26 【问题描述】:我正在尽我最大的努力围绕 arel 及其背后的关系代数弯曲我的大脑,但是如何表示 SELECT DISTINCT
一直是我无法理解的。谁能解释一下如何做:
SELECT DISTINCT title FROM posts;
非常感谢!
【问题讨论】:
我不知道 arel,但是根据我对 C.J.Date 的“Database in Depth”的阅读,在关系代数中,查询的结果是一组元组。因此,如果 arel 遵循这一理论,则默认值应该是 distinct。 【参考方案1】:Post.select('DISTINCT title')
更新 1:
在发帖时,这在 Arel 中不可用。现在,ActiveRecord::QueryMethods 有 uniq
方法 (http://apidock.com/rails/ActiveRecord/QueryMethods/uniq),所以你想要:
Post.select(:title).uniq
更新 2: 看起来 Arel 现在支持这种行为。 @maerics 有正确的答案。如果它不是被接受的答案,我会删除它。
【讨论】:
不完全是代数,但很难与它的效率争论;-) 这种方法有一个致命的问题:如果您有多个范围和一个 select 语句,将它们链接在一起会导致 SQL 无效。 这不是 AREL,因此无法回答问题。【参考方案2】:前面的答案是 Rails 方式,不是吗?不是阿雷尔的方式。
这适用于arel 1.x:
posts = Table(:posts)
posts.project(Arel::Distinct.new(posts[:title]))
我猜还有另一种“更正确”的方法可以通过 API 做到这一点,但我还没有弄清楚。
【讨论】:
这是真的。此答案适用于 Arel 1.x,将不再有效。 你知道有什么替代方案吗?【参考方案3】:Arel 的做法是:
t = Arel::Table.new(:foo)
count_distinct = t[:field].count(true)
count_distinct.to_sql # => "COUNT(DISTINCT `foo`.`field`)"
【讨论】:
这并没有严格回答这个问题,但它确实回答了 my 问题:你如何使用 Arel 表达count(DISTINCT attr)
。【参考方案4】:
由于 AREL 在其操作中始终使用 SET,重复的行结果将被自动删除。只需使用普通的 Project (Phi) 操作即可。
【讨论】:
这在理论上是个好主意,但在现实中显然是错误的。 Arel 查询将从任何投影返回重复条目,除非明确受到“distinct”方法的约束。【参考方案5】:使用纯 Arel(不是 Rails/ActiveRecord)有一个“不同”的方法:
Arel::VERSION # => '3.0.2'
posts = Arel::Table.new(:posts)
posts.project(posts[:title])
posts.distinct
posts.to_sql # => 'SELECT DISTINCT "posts"."title" FROM "posts"'
奇怪的是,根据其他 Arel 方法,“distinct”方法是不可链接的。
【讨论】:
对于 Arel 版本,5.0.1
,这不再有效 :(.
Arel 6,一切正常。它也是可链接的,因为它返回 SelectManager。
arel 6.0.3 这节省了我的时间,虽然我使用了distinct_on
【参考方案6】:
如果您使用范围执行此操作:
scope :recent, lambda |count|
select("DISTINCT posts.*").
joins(:whatever).
limit(count).
order("posts.updated_at DESC")
【讨论】:
以上是关于如何使用 arel/关系代数获取不同的值的主要内容,如果未能解决你的问题,请参考以下文章