Rails 4 запрос уникальный по одному атрибуту


Так что это скорее вопрос арела, чем что-либо еще, но вот что я пытаюсь сделать.

У меня есть три объекта, скажем, называемые элементами

<Item id: 1, name: 'Book'>
<Item id: 2, name: 'Car'>
<Item id: 3, name: 'Book'>

Я хочу сделать запрос, который просто вернет только один из каждого уникального атрибута "name".

Что-то вроде Item.select('distinct(name), items.*')

Это не работает, хотя он по-прежнему возвращает все три элемента.

Как я могу сформировать этот запрос так, чтобы он возвращал только:

<Item id: 1, name: 'Book'>
<Item id: 2, name: 'Car'>
6 17

6 ответов:

Если вы хотите вернуть всю модель, но при этом сохранить уникальность, вы можете использовать следующее:

Item.select('distinct on (name) *')

Я проверил это только с базой данных Postgres. Он может работать или не работать с mysql.

Пожалуйста, попробуйте это:

Item.select('distinct name')

Если вам нужен только массив с именами, без идентификатора, вы можете сделать:

Item.pluck(:name).uniq

Результат SQL-запроса:

#=> SELECT `items`.`name` FROM `items`

** edit * *

uniq выполняется на массиве записей. Будьте осторожны, если вы ожидаете много записей. SQL Distinct работает намного быстрее.

Если это так, используйте ответ ви выше, с map:

Item.select('distinct name').map(:name)

В Rails 4 Попробуйте Items.all.to_a.uniq { |item| item.name }

В Rails 3 Вы должны быть в состоянии просто сделать Items.uniq_by { |item| item.name }

Когда вы вызываете uniq на массиве, вы можете передать ему блок, чтобы диктовать, как определить уникальность. В Rails 3 раньше можно было использовать uniq_by, но в Rails 4 это стало устаревшим. Поэтому один из методов, который я нашел, заключается в том, чтобы просто преобразовать отношение ActiveRecord в массив и вызвать uniq на этом.

Для Mysql вы можете использовать group с ONLY_FULL_GROUP_BY отключено,

Item.group(:name).to_sql
=> "SELECT `items`.* FROM `items`  GROUP BY name"

Смотрите есть ли возможность ANY_VALUE для mysql 5.6?

Ниже приведен запрос Rails ORM, который даст желаемый результат со всеми последними версиями rails rails 5.X.

@unique_values= []
Model.all.group_by(&:column_name).each do |key, val|
    if val.count == 1
      @unique_values << val
    else
      @unique_values << val.first
    end
end