SQL:为唯一ID和重复数据删除选择前N个条目

时间:2015-09-15 01:39:29

标签: mysql sql select where-clause

我有一个看起来像这样的表:

HorseID     RiderID     Total
121         1           2
5           1           150
600         1           20
30          2           500
5           3           10
600         3           10
34          3           10

每匹马可能有多个骑手,反之亦然。 '总'指骑手与骑马相结合的事故总数。我想要的是一张表格,其中包含每位骑手的总排名为2的HorseIDs,并进行了重复数据删除。 (即,骑手1的顶级马匹是5匹马,因为他们共同发生了150起事故,而其他骑马1匹的情况则为20和2)。所以我想在这里输出的是:

HorseID
5
600
30

注意当骑手少于2匹马时,应该抓住前1名。当谈到骑手3时,有一个平局,所以它按顺序选择前2名 - 但是,这些已经在列表中,所以没有添加(重复数据删除部分 - 也很乐意在之后的单独步骤中进行重复数据删除,如果这样做& #39;更快)。我不会介意这是否会在平局中抓住第34位(所以我们在列表中有一个额外的马匹),任何解决平局的方法都很好。

这是一个玩具数据集,真正的数据集要大得多,我会抓住每个RiderID的前200名,因此可扩展/高效的解决方案会很棒。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

这只是一个稍微修改过的source问题。由于MySQL缺乏分析功能,因此MySQL并不是最好的每组最好的,但你可以这样做:

SELECT DISTINCT HorseID
FROM (SELECT HorseID, RiderID, Total,
        @num := IF(@group = RiderID, @num + 1, 1) AS row_number,
        @group := RiderID AS group
    FROM UnnamedTable
    ORDER BY RiderID, Total DESC, HorseID) ranked
WHERE row_number <= 2;

请注意,处理关系。如果前三匹马的总数为200,那么你仍然只能获得两排。请注意,子查询的ORDER BY中的第三项是HorseID。这只是在结果的情况下使结果具有确定性。您可以通过向IF()表达式添加一点逻辑来处理关系,并将其从greatest-n-per-group更改为类似ROW_NUMBER()。但是,如果你想让它像DENSE_RANK()那样,我认为你需要第三个变量。

我不确定这种情况有多好。