Pregunta

Tengo una tabla con (entre otras cosas) un nombre y un rango. Me gustaría devolver el conjunto de todos los nombres únicos, pero regresó para cada nombre, me gusta escoger la fila con el rango más alto. Esto es muy sencillo con dos instrucciones SELECT anidadas:

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

MySQL toma el primer "hit" para cada nombre, que (debido a la orden anterior POR) siempre será la de más alto rango.

Ahora, si quiero conectar en esta tabla con ActiveRecord, estoy en un poco de una pérdida. Yo sólo podía tirar lo anterior en find_by_sql, pero que sólo se siente sucio. He intentado algo así como

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

Creo que funciona , pero todavía se siente como que debe haber una mejor manera. Resolverlo, ya sea a través de ActiveRecord engaño o una más elegante manipulación de matrices sería bienvenido!

¿Fue útil?

Solución

  

MySQL toma el primer "hit" para cada nombre, que (debido a la orden anterior POR) siempre será la de más alto rango.

La consulta que utiliza para devolver la fila superior en el grupo es no garantizada. Es sólo una coincidencia de la aplicación, y es sujeto a cambios. No confíe en esto.

Usted está tratando de resolver el " grupo mayor-n-por-" problema que me veo publicado en StackOverflow frecuencia. Aquí es una consulta que obtiene la respuesta más fiable:

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;

Alternativa que hace lo mismo que:

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

Yo podría simplemente tirar lo anterior en find_by_sql, pero que sólo se siente sucio.

ActiveRecord es muy útil para ciertos tipos de consultas, pero no se puede resolver todas las consultas de base de datos con ActiveRecord. Cuanto antes que llegue a esta noción más pronto realizar su trabajo y tener éxito. SQL no va a morder.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top