【问题标题】:Get Top 3 Scores for Each Month For Each Person in a Pool获得池中每个人每月的前 3 名
【发布时间】:2021-02-17 14:22:29
【问题描述】:

我有一个 PostgreSQL 数据库,用于跟踪魔术池中的人的得分。池中的每个玩家都可以在给定的月份内玩多场比赛,有时在给定的一天也可以玩多场比赛。

例如玩家 1,10 月份打了 5 场比赛,总共 11 分,11 月份打了 6 场比赛,根据每个月的所有比赛得分,总共 62 分

Game#   Game Date     Points Earned
1      02-Oct-2020      3
2      02-Oct-2020      2
3      09-Oct-2020      3
4      10-Oct-2020      1
5      24-Oct-2020      2
6      02-Nov-2020      4
7      06-Nov-2020      32
8      06-Nov-2020     -4
9      07-Nov-2020      33
10     07-Nov-2020      1
11     10-Nov-2020     -4

我要做的是让玩家每个月的前 3 名得分。 10 月总计 8 分 (3+2+3),11 月总计 69 分 (32+33+4)。

当我只有一个月的时间时,我可以毫无问题地获得当月的前 3 名;但是现在我有好几个月的时间,我无法让我的代码工作。我已经修改了我的原始代码,这就是我想出的

SELECT
  player_name, 
  EXTRACT(MONTH FROM game_date) AS game_month,
  sum(player_pts) AS monthly_pts
FROM testdb.player_points
WHERE player_name = 'player1'
    GROUP BY player_name, game_month
    ORDER BY game_month
    LIMIT 3;

上面的代码返回给我的是每个月的总积分。 10 月为 11,11 月为 62,根据我的代码,这是我所期望的;但不是我想要的。我尝试过使用 INNER JOINS、基于月份的分区、子查询;但似乎没有什么能给我我想要的东西。我得到的最干净的结果是上面的代码。我正在寻找关于如何获得我需要的东西的一些指导。提前致谢。

【问题讨论】:

    标签: sql postgresql sum aggregate-functions greatest-n-per-group


    【解决方案1】:

    如果您想要每个玩家和每个月的前三名,请使用窗口函数:

    select *
    from (
        select pp.*, 
            row_number() over(partition player_name, date_trunc('month', game_date) order by player_pts desc) rn
        from testdb.player_points pp
    ) pp
    where rn <= 3
    

    然后您可以按玩家和月份汇总结果,如果这是您想要的:

    select player_name, game_month, sum(player_points) top_3_points
    from (
        select pp.*, d.*
            row_number() over(partition pp.player_name, d.game_month order by pp.player_pts desc) rn
        from testdb.player_points pp
        cross join lateral (values (date_trunc('month', game_date))) d(game_month)
    ) pp
    where rn <= 3
    group by player_name, game_month
    

    我将日期截断移动到横向连接,因此我不必输入两次。如果您想要特定玩家的结果,那么您可以使用where 子句(最好直接放在子查询中)。

    【讨论】:

    • 谢谢。我一直在寻找按玩家和月份汇总结果。我的一次尝试中有类似的东西。但从未使用 row_number() 来获得我想要的东西。
    • 完成。不过我确实有一个问题,因为我不确定我是否理解“d(game_month)”在做什么。是为“game_month”创建别名“d”还是创建别名“d”和别名“game_month”?我以前从未见过这样写的别名。
    猜你喜欢
    • 2021-10-01
    • 1970-01-01
    • 2021-04-07
    • 2020-01-05
    • 2022-12-15
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多