2010-06-28 10 views
11

Hago todo lo posible para inclinar mi cerebro en torno al arel y al álgebra relacional detrás de él, pero la forma de representar un SELECT DISTINCT siempre elude mi comprensión. ¿Alguien puede explicar cómo arel:Cómo recuperar valores distintos con arel/álgebra relacional

SELECT DISTINCT title FROM posts; 

Muchas gracias!

+1

no sé Arel pero desde mi lectura de "base de datos en profundidad" por CJDate, en el álgebra relacional el resultado de una consulta es un conjunto de tuplas. Entonces, si arel está siguiendo esta teoría, distinto debería ser el predeterminado. –

Respuesta

1

Post.select('DISTINCT title')

Actualización 1:

En el momento de la entrada, esto no estaba disponible en Arel. En estos días, ActiveRecord :: QueryMethods tiene la uniq método (http://apidock.com/rails/ActiveRecord/QueryMethods/uniq), por lo que querrían:

Post.select(:title).uniq 

Actualización 2: Parece que Arel ahora es compatible con este comportamiento. @maerics tiene la respuesta correcta. Eliminaría esto si no fuera la respuesta aceptada.

+0

No es exactamente algebraico, pero es difícil argumentar con su eficacia ;-) – jemmons

+2

Hay un problema fatal con este enfoque: si tiene más de un ámbito con una instrucción select, encadenándolos puede causar SQL no válido. –

+5

Esto no es AREL, y por lo tanto no responde la pregunta. –

6

La respuesta anterior es la de Rails, ¿no? No es el camino de Arel.

Esto funciona para 1.x:

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

supongo que hay otra forma "más correcta" de hacerlo a través de la API, pero no me he dado cuenta de eso todavía.

+4

Esto parece no funcionar ahora. –

+1

Esto es cierto. Esta respuesta fue para Arel 1.x y ya no funcionará. – numbers1311407

+1

¿Sabes cuál es la alternativa? –

3

Si usted está haciendo esto se utiliza un microscopio:

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

Desde AREL utiliza siempre situado en su funcionamiento, resultados de filas duplicadas se eliminarán de forma automática. Solo usa una operación de Proyecto normal (Phi).

+0

Esta es una buena idea en teoría pero es evidentemente falsa en la realidad. Las consultas Arel devolverán entradas duplicadas de cualquier proyección, a menos que el método "distinto" las restrinja explícitamente. – maerics

12

Usando puro Arel (no Rails/ActiveRecord) hay un método "distinta":

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"' 

Curiosamente, el método "distinta" no se encadenables, por los otros métodos Arel.

+0

¡He estado buscando esto por un tiempo, muchas gracias! – Joe

+0

Con la versión de Arel, '5.0.1', esto ya no funciona :(. –

+1

Arel 6, todo funciona perfectamente. También es encadenable, ya que se devuelve SelectManager. – Slotos

8

La forma Arel de hacerlo es:

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

' count (true) 'funciona muy bien para Arel 3 –

Cuestiones relacionadas