使用 SQLite 在单个 SQL 查询中实现 Elo 计算

问题描述 投票:0回答:1

我正在尝试在单个 SQL 查询中实现 Elo 评级计算,但无法使其工作。我找到了一篇关于如何使用 Postgres 的文章,但我不使用 SQLite。另外,我的表架构有点不同:

CREATE TABLE teams (
  name TEXT NOT NULL PRIMARY KEY
)

CREATE TABLE games (
  "winner_team" TEXT REFERENCES teams,
  "loser_team" TEXT REFERENCES teams
)

到目前为止,我有以下代码(为了简化问题,我在这里只查看获胜团队,并将 elo 加 1,而不是进行完整计算):

WITH RECURSIVE elo_ratings(current_game_num, team, previous_elo, new_elo) AS (
  -- Initialize all teams with the default elo
  SELECT
    0 AS game_number,
    name,
    1000.0 AS previous_elo,
    1000.0 AS new_elo
  FROM teams

  UNION

  SELECT
    rowid AS game_number,
    winner_team,
    elo_ratings.new_elo as previous_elo,
    elo_ratings.new_elo + 1
  FROM games
  JOIN elo_ratings ON current_game_num == games.rowid - 1
  LIMIT 10000
)
SELECT * 
FROM elo_ratings

但是使用这段代码,就有一个全局的

elo_rating
,而不是每个玩家都有一个不同的。

这如何才能完成?

sql sqlite common-table-expression elo
1个回答
0
投票

我还无法想出一个纯 SQL 解决方案,但有办法使用 JSON 对象作为中间“表”来实现它。这实际上可能是一个更好的解决方案。

WITH  RECURSIVE elo_ratings(current_game_num, elo_map, utc) AS (
  SELECT
    0 AS game_number,
    -- Track all elo ratings in a JSON object
    -- (initialized to 1000 here)
    json_group_object(name, 1000.0) as elo_map,
    '1970-01-01T00:00:00Z'
  FROM teams

  UNION

  SELECT
    rowid AS game_number,
    -- Apply elo rating changes to JSON object
    json_patch(
      json_patch(
        elo_map, 
        json_object(
          winner_team, 
          elo_map->>winner_team + (32 * (1 -
              ((pow(10, elo_map->>winner_team / 400))  /
              (pow(10, elo_map->>winner_team / 400) + pow(10, elo_map->>loser_team / 400)))
            )
          )
        )
      ),
      json_object(
        loser_team,
        elo_map->>loser_team + (32 * (0 -
            ((pow(10, elo_map->>loser_team / 400)) /
            (pow(10, elo_map->>winner_team / 400) + pow(10, elo_map->>loser_team/ 400)))
          )
        )
      )
    ),
    games.utc
  FROM games
  JOIN elo_ratings ON current_game_num == games.rowid - 1
  ORDER BY games.utc
)
SELECT DISTINCT key, value
FROM (SELECT * FROM elo_ratings ORDER BY current_game_num DESC LIMIT 1), json_each(elo_map)
ORDER BY value DESC
© www.soinside.com 2019 - 2024. All rights reserved.