Как получить отличные значения с помощью isl/реляционной алгебры

Я делаю все возможное, чтобы согнуть мой мозг вокруг arel и реляционную алгебру за ним, но как представить SELECT DISTINCT, постоянно ускользает от моего понимания. Может ли кто-нибудь объяснить, как isl:

SELECT DISTINCT title FROM posts; 

Большое спасибо!

Ответ 1

Post.select('DISTINCT title')

Обновление 1:

Во время публикации это было недоступно в Ареле. В наши дни ActiveRecord:: QueryMethods имеет метод uniq (http://apidock.com/rails/ActiveRecord/QueryMethods/uniq), поэтому вам нужно:

Post.select(:title).uniq

Обновление 2: Похоже, что Arel теперь поддерживает это поведение. @maerics имеет правильный ответ. Я бы удалил это, если бы это был не принятый ответ.

Ответ 2

Используя чистый 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.

Ответ 3

Способ Arel:

t = Arel::Table.new(:foo)
count_distinct = t[:field].count(true)
count_distinct.to_sql # => "COUNT(DISTINCT `foo`.`field`)"

Ответ 4

Предыдущий ответ - путь Rails, нет? Не путь Ареля.

Это работает для 1. х:

posts = Table(:posts)
posts.project(Arel::Distinct.new(posts[:title]))

Я бы предположил, что существует еще один "более правильный" способ сделать это через API, но я еще не понял этого.

Ответ 5

Если вы делаете это с помощью области действия:

  scope :recent, lambda {|count|
    select("DISTINCT posts.*").
    joins(:whatever).
    limit(count).
    order("posts.updated_at DESC")
  }

Ответ 6

Так как AREL всегда использует SET в нем, дублирующиеся результаты строки будут удалены автоматически. Просто используйте обычную операцию Project (Phi).