Rails: seleccionar valores únicos de una columna


Ya tengo una solución que funciona, 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

Author: alexandrecosta, 2012-03-12

11 answers

Model.select(:rating)

El resultado de esto es una colección de objetos Model. No son calificaciones 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 rails 5.0.0.1, solo funciona en consultas de "nivel superior", como la anterior. No funciona en proxies de colección (relaciones" has_many", por ejemplo).

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

En este caso, deduplicar después de la consulta

user.addresses.pluck(:city).uniq # => ['Moscow']
 386
Author: Sergio Tulentsev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-14 04:51:47

Si vas a usar Model.select, entonces también podrías usar DISTINCT, ya que devolverá solo los valores únicos. Esto es mejor porque significa que devuelve menos filas y debería ser ligeramente 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 su base de datos entiende la palabra clave DISTINCT, y la mayoría debería.

 81
Author: kakubei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-04 19:46:31

Esto también funciona.

Model.pluck("DISTINCT rating")
 51
Author: Nat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-25 12:05:52
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

 24
Author: Cameron Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-19 18:34:16
Model.select(:rating).uniq

Este código funciona como 'DISTINTO' (no como Array#uniq) desde rails 3.2

 20
Author: kuboon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-04 06:49:35

Si también desea seleccionar campos adicionales:

Model.select('DISTINCT ON (models.ratings) models.ratings, models.id').map { |m| [m.id, m.ratings] }
 18
Author: Marcin Nowicki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-05 09:47:09

Si alguien está buscando lo mismo con Mongoid, es

Model.distinct(:rating)
 4
Author: Vassilis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-08 00:12:49

Si voy derecho al camino entonces:

Consulta actual

Model.select(:rating)

Está devolviendo la matriz de objeto y ha escrito la consulta

Model.select(:rating).uniq

Uniq se aplica en la matriz de objetos y cada objeto tiene un id único. uniq está realizando su trabajo correctamente porque cada objeto en la matriz es uniq.

Hay muchas maneras de seleccionar una calificació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: buscar distinto datos por consulta SQL.

Estas consultas se considerarán "londres" y "londres" mismo significa que se descuida al espacio, es por eso que seleccionará 'londres' una vez en el resultado de su consulta.

Tercera y cuarta pregunta:

Buscar datos por consulta SQL y para datos distintos aplicado ruby uniq mehtod. estas consultas se considerarán" londres "y" londres " diferentes, es por eso que seleccionará 'londres' y 'londres' ambos en el resultado de su consulta.

Por favor, prefiera la imagen adjunta para más entender y echar un vistazo a "Toured / Awaiting RFP".

introduzca la descripción de la imagen aquí

 4
Author: uma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-12 19:04:53

Algunas respuestas no tienen en cuenta que el OP quiere un array de valores

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

Dicho esto, creo que una buena respuesta es:

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

Porque, primero genera una matriz de Modelo (con tamaño disminuido debido a la selección), luego extrae el único atributo que tienen los modelos seleccionados (calificaciones)

 3
Author: Fernando Fabreti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-25 13:04:04
Model.select(:rating).distinct
 1
Author: hassan_i,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-16 14:22:20

Otra forma de recopilar columnas uniq con sql:

Model.group(:rating).pluck(:rating)
 0
Author: Vyacheslav Zharkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-09 14:34:18