Rieles: seleccione valores únicos de una columna

Ya tengo una solución de trabajo, pero realmente me gustaría saber por qué esto no funciona:

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

Selecciona, pero no imprime valores únicos, imprime todos los valores, incluidos los duplicados. Y está en la documentación: http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields

 Model.select(:rating) 

El resultado de esto es una colección de objetos Model . Clasificaciones no simples. Y desde el punto de vista de uniq , son completamente diferentes. Puedes usar esto:

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

o esto (más eficiente)

 Model.uniq.pluck(:rating) # rails 5+ Model.distinct.pluck(:rating) 

Actualizar

Aparentemente, a partir de los Rails 5.0.0.1, funciona solo en consultas de “nivel superior”, como en el ejemplo anterior. No funciona en proxies de recostackción (relaciones “has_many”, por ejemplo).

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

En este caso, deduplicate después de la consulta

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

Si va a usar Model.select , entonces también podría usar DISTINCT , ya que solo devolverá los valores únicos. Esto es mejor porque significa que devuelve menos filas y debe ser un poco más rápido que devolver un número de filas y luego decirle a Rails que elija los valores únicos.

 Model.select('DISTINCT rating') 

Por supuesto, esto se proporciona si su base de datos comprende la palabra clave DISTINCT , y la mayoría debería hacerlo.

Esto también funciona

 Model.pluck("DISTINCT rating") 
 Model.uniq.pluck(:rating) # SELECT DISTINCT "models"."rating" FROM "models" 

Esto tiene las ventajas de no usar cadenas sql y no crear instancias de modelos

 Model.select(:rating).uniq 

Este código funciona como ‘DISTINCT’ (no como Array # uniq) desde los carriles 3.2

Si desea también seleccionar campos adicionales:

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

Si alguien está buscando lo mismo con Mongoid, eso es

 Model.distinct(:rating) 

Si voy directo a la manera entonces:

Consulta actual

 Model.select(:rating) 

está devolviendo una matriz de objeto y has escrito una consulta

 Model.select(:rating).uniq 

uniq se aplica a una matriz de objetos y cada objeto tiene una identificación única. uniq está realizando su trabajo correctamente porque cada objeto en la matriz es uniq.

Hay muchas formas de seleccionar una clasificación distinta:

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

o

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

o

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

o

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

Una cosa más, primera y segunda consulta: encuentre datos distintos por consulta SQL.

Estas consultas se considerarán “londres” y “londres”, lo que significa que omitirá el espacio, por eso seleccionará “Londres” una vez en el resultado de su consulta.

Consulta tercera y cuarta:

encontrar datos por consulta SQL y para distintos datos aplicados ruby ​​uniq mehtod. estas consultas se considerarán “london” y “london” diferentes, por eso seleccionará “london” y “london” en el resultado de su consulta.

por favor, prefiera adjuntar la imagen para mayor comprensión y eche un vistazo a “Solicitud de presupuesto / espera de solicitud de propuesta”.

enter image description here

Algunas respuestas no tienen en cuenta que OP quiere una matriz de valores

Otras respuestas no funcionan bien si su modelo tiene miles de registros

Dicho eso, creo que una buena respuesta es:

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

Porque, primero generas una matriz de Modelo (con tamaño reducido debido a la selección), entonces extraes el único atributo que tienen los modelos seleccionados (calificaciones)

 Model.select(:rating).distinct 

Otra forma de recolectar columnas uniq con sql:

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