在 Postgres 中的连胜纪录

Posted

技术标签:

【中文标题】在 Postgres 中的连胜纪录【英文标题】:Winning streaks in Postgres 【发布时间】:2018-08-08 09:42:29 【问题描述】:

正如标题所说 - 我有一个包含球员和比赛的 Postgres 数据库,我想获得连胜记录的列表。请注意,我不仅对数字感兴趣,也就是说,我在 *** 上看到很多关于最高连胜的问题 - 我希望能够获得更多关于连胜的数据和详细信息,例如所有游戏。

具体来说,这是我正在查看的数据库:http://aligulac.com/about/db/。我基于此创建了一个包含基本列的视图,基本上如下所示:

player_id | match_id | score
-------------------------------
82        | 2847     |  2
82        | 3733     |  3
82        | 4348     |  1
82        | 5237     |  1
82        | 5363     |  3
82        | 7274     | -1
51        | 2347     |  3
51        | 3746     |  2
51        | 5037     |  3
51        | 7269     | -1
...       | ...      |  ...

“score”是“player_score -对手score”,所以我想要来自同一玩家的连续正分数,而不会中断。结果表可能如下所示:

player_id | match_id | streak
-------------------------------
82        | 5363     |  5
51        | 5037     |  3
...       | ...      |  ...

这将允许我检索连胜的最后一场比赛,因为我知道连胜的时间,所以我也知道连胜之前的所有比赛。有没有一种存储 ID 数组的好方法,以便我可以存储所有相关的 matchID,这些 matchID 也是行中连胜的一部分?也许在一个枚举左右?

到目前为止,我所做的是制作所有比赛的 Postgres 视图,按玩家 ID/比赛 ID 排序,将其导出到 Excel CSV,然后使用 Excel 公式 + 过滤器得出结果。目前看起来像this。但当然,这并不容易更新,我希望能够直接通过 Query 进行更新,或者至少是其中的一部分 - 或者更好地使用 Aligulac API (http://aligulac.com/about/api/)。

关于如何按照这些思路做某事的任何想法?谢谢!

【问题讨论】:

这里的大多数人都想要格式化的文本,而不是图像——甚至更糟——图像的链接。 听起来像是“差距和孤岛”问题。 对不起@jarlh - 不知道情况如此糟糕。这些不是图片链接,而是数据库链接和生成的 Google Sheets 表格以提供一些上下文。但我已经添加了抽象问题核心的表格,希望有助于使其更易于访问。感谢有关如何改进问题或潜在解决方案的任何其他建议。 在您看来,您需要一个定义行顺序的列,您无法在无序数据集上找到系列。该列可以是例如整数主键或时间戳/日期列(匹配日期),或类似的东西。 @klin 好点,没想到。创建视图时,我按“player_id,match_id”对其进行排序,然后将其导出到 Excel - 效果很好。比赛日期无关紧要,因为每个球员每天经常有很多比赛,所以 match_id 可能是一个更好的顺序。我可以只使用元组“player_id,match_id”吗?由于您无法将主键添加到 Postgres 视图。 【参考方案1】:

使用两个窗口函数来指定序列和聚合函数以获得最长的连续:

select distinct on (player_id)
    player_id, 
    max(match_id) as match_id, 
    count(*) as streak
from (
    select 
        player_id, match_id, score, 
        sum(grp) over w as grp
    from (
        select 
            player_id, match_id, score, 
            (score < 0 and lag(score, 1, 1) over w > 0)::int as grp
        from my_view
        window w as (partition by player_id order by match_id)
        ) s
    window w as (partition by player_id order by match_id)
    ) s
where score > 0
group by player_id, grp
order by player_id desc, streak desc

 player_id | match_id | streak 
-----------+----------+--------
        82 |     5363 |      5
        51 |     5037 |      3
(2 rows)    

【讨论】:

非常感谢您提供此解决方案。我花了一段时间才找到时间来实现它,然后弄清楚它的作用,它是如何工作的,以及如何根据我的需要调整它(在我看来也发现了一个错误,所以这是一个痛苦但有帮助的练习)。我省略了“distinct”子句和最大值,因为我对所有连胜感兴趣,而不仅仅是每个球员的最佳连胜。但我想这在我的帖子中并不清楚,所以它在我身上,毕竟这一切都帮助我加深了对 Postgres 的理解。现在我可以用这个做很多有趣的事情。谢谢!

以上是关于在 Postgres 中的连胜纪录的主要内容,如果未能解决你的问题,请参考以下文章

在熊猫队中连续几周获得最长连胜纪录

TypeORM 中的 Postgres 枚举

使用 Postgres JDBC 恢复数据库中的 postgres 备份数据(数据库名称包含空格)

Postgres 中的库存计算

从雪花中的 Postgres 复制 FILTER 子句

如何按postgres数组中的多个ID分组