2009-12-04 1 views
2

У меня есть таблица с (между прочим) именем и званием. Я хотел бы вернуть набор всех уникальных имен, но для каждого возвращаемого имени я хотел бы выбрать строку с самым высоким рангом. Это просто с двумя вложенными ЗЕЬЕСТ:ActiveRecord вложен SELECT - могу ли я сделать это без ручного SQL?

SELECT * FROM (SELECT * FROM foo ORDER BY rank DESC) AS ordered GROUP BY name 

MySQL принимает первый «удар» для каждого имени, которое (из ранее ORDER BY) всегда будет самым высокопоставленным один.

Теперь, если я хочу подключиться к этой таблице с помощью ActiveRecord, я немного потеряю. Я мог бы просто выбросить это в find_by_sql, но это просто чувствует себя грязным. Я пытался что-то вроде

result = foo.all 
result.delete_if do |item| 
    isOutranked = false 
    result.each do |row| 
    if (row.name == item.name) and (row.rank > item.rank) then isOutranked = true 
    end 
    isOutranked 
end 

Я думаю, что работает, но он все еще чувствует, что должен быть лучший способ. Разрешить его либо с помощью обманки ActiveRecord, либо более элегантное манипулирование массивами было бы очень желанным!

ответ

2

MySQL берет первый «хит» для каждого имени, которое (из-за более раннего ORDER BY) всегда будет самым высоким.

Запрос вы используете, чтобы вернуть верхнюю строку в группе не гарантировано. Это только совпадение с реализацией, и оно может быть изменено. Не полагайтесь на это.

Вы пытаетесь решить проблему «greatest-n-per-group», которую я часто просматриваю в StackOverflow. Вот запрос, который получает ответ более надежно:

SELECT t1.* 
FROM foo AS t1 
LEFT OUTER JOIN foo AS t2 
ON (t1.name = t2.name AND t1.rank < t2.rank) 
WHERE t2.name IS NULL; 

Альтернатива, которая делает то же самое:

SELECT * 
FROM foo AS t1 
WHERE NOT EXISTS 
    (SELECT * FROM foo AS t2 
    WHERE t1.name = t2.name AND t1.rank < t2.rank); 

я мог просто бросить выше в find_by_sql, но это просто чувствует себя грязным.

ActiveRecord очень удобен для определенных видов запросов, но вы не можете решить каждый запрос базы данных с помощью ActiveRecord. Чем скорее вы поймете это понятие, тем скорее вы получите свою работу и добьетесь успеха. SQL не собирается вас укусить.

 Смежные вопросы

  • Нет связанных вопросов^_^