#ruby-on-rails #ruby-on-rails-3
#ruby-on-rails #ruby-on-rails-3
Вопрос:
Я погружаюсь в Rails и изучаю, как использовать ActiveRecord, и я создал модель проигрывателя, у которой есть атрибут score. Я пытаюсь найти эффективный способ запросить базу данных для игрока (ов) с наибольшим количеством баллов. В случаях, когда два или более игроков равны по наибольшему количеству очков, мне понадобятся все игроки. Я могу выяснить, как это сделать, сначала отсортировав список, но я не был уверен, нужно ли это. Какой наиболее эффективный способ получить набор игроков с наибольшим количеством баллов?
Кроме того, улучшит ли создание индекса в БД для столбца оценки скорость выполнения этого запроса?
Большое спасибо за вашу мудрость!
Ответ №1:
Player.order("score DESC").limit(50)
Должно быть просто вот так. Взгляните на руководства rails.
Или, еще лучше, сделайте что-то вроде этого:
high_score = Player.maximum(:score)
high_score_players = Player.where(:score => high_score).all
Комментарии:
1. Я думаю, что последняя строка должна быть
high_score_players = Player.find_all_by_score(high_score)
(обратите внимание на find_all …), потому что может быть несколько игроков с наибольшим количеством баллов.2. @Alex — Хороший улов, я обновил его, чтобы вместо этого использовать
where
метод. Я никогда не использовалfind_all_by...
Ответ №2:
Если вы запрашиваете столбец как часть WHERE
or ORDER BY
, у вас почти всегда должен быть индекс. Без индекса ваша база данных должна выполнять сканирование таблицы, и каждый из них обходится дорого.
Захват игрока или игроков с наибольшим количеством баллов может быть выполнен в два прохода, сначала для определения наибольшего количества баллов, затем для выборки всех игроков с этим результатом:
@players = Player.where("score=(SELECT MAX(score) FROM #{Player.table_name}").all
Комментарии:
1. Этот запрос очень специфичен для базы данных, и весь смысл Rails в том, чтобы устранить необходимость вводить SQL. Хотя ваш запрос может быть корректным, он не очень «похож на rails»
2. AREL намного лучше генерирует запросы, но это все еще не так хорошо, как вы можете сделать сами, если вы знаете, какую СУБД используете. Ваш подход более общий, но требует двух запросов и занимает немного больше времени. Не имеет большого значения, если он вызывается только один раз за рендеринг, и больше зависит от платформы, что неплохо.