2

我有一张桌子,上面有(除其他外)名字和等级。我想返回所有唯一名称的集合,但是对于返回的每个名称,我想选择排名最高的行。这很简单,有两个嵌套的 SELECT 语句:

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 技巧或更优雅的数组操作来解决它!

4

1 回答 1

2

MySQL 为每个名称获取第一个“命中”,(因为更早的 ORDER BY)将始终是排名最高的。

不能保证您用于返回组中第一行的查询。这只是实施的巧合,可能会发生变化。 不要依赖这个。

您正在尝试解决我经常在 StackOverflow 上看到的“每组最大 n ”问题。这是一个更可靠地获得答案的查询:

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 不会咬你。

于 2009-12-04T00:31:52.710 回答