【问题标题】:SQL: Select top N entries for a unique id and deduplicateSQL:为唯一 id 选择前 N 个条目并删除重复数据
【发布时间】:2015-12-11 03:17:44
【问题描述】:

我有一张如下所示的表格:

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 个 HorseID,已删除重复数据。 (即,骑手 1 的顶级马是马 5,因为他们一起发生了 150 次事件,而骑手 1 的其他马匹有 20 次和 2 次)。所以我想要的输出是:

HorseID
5
600
30

请注意,当骑手少于 2 匹马时,它应该只抓住前 1 匹。当涉及到骑手 3 时,有一个平局,因此它会根据顺序选择前 2 个 - 但是,这些已经在列表中,所以没有添加(去重部分 - 如果是这样的话,也很乐意在单独的步骤中进行去重快点)。我不介意这是否在平局中获得了 34 号(所以我们在名单上多了一个马匹),任何解决平局的方法都可以。

这是一个玩具数据集,实际数据集要大得多,我将为每个 RiderID 争取前 200 名,所以一个可扩展/高效的解决方案会很棒。

我该怎么办?

【问题讨论】:

  • 你需要更好地解释上半部分。在你的脑海中没有出现在屏幕上。然后你需要展示你尝试过的代码

标签: mysql sql select where-clause


【解决方案1】:

这只是一个稍加修改的greatest-n-per-group 问题。 MySQL 不是最好的 best-n-per-group,因为它缺乏分析功能,但你可以这样做:

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() 表达式添加一点逻辑并将其从ROW_NUMBER() 更改为DENSE_RANK() 来处理平局。但是,如果您希望它像RANK(),我认为您需要在其中添加第三个变量。

我也不确定它的扩展性如何。

【讨论】:

  • 最后,你对我们全神贯注。另外,你忘了初始化你的变量
  • @Strawberry Oracle、Postgres、SQL Server、DB2、Sybase、Firebird、Informix。许多 RDBMS 支持分析功能。 MySQL 有点不寻常,因为 not 这样做。 SQLite 也没有,但这并不奇怪。
猜你喜欢
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多