累积游戏分数 SQL

Sim*_*Loh 3 sql-server

我最近开发了一个游戏,数据库运行在 MSSQL 上。

这是我的数据库结构

表:播放器

PlayerID uniqueIdentifier (PK)
PlayerName nvarchar
Run Code Online (Sandbox Code Playgroud)

表:游戏结果

ID bigint (PK - Auto Increment)
PlayerID uniqueIdentifier (FK)
DateCreated Datetime
Score int
TimeTaken bigint
PuzzleID int
Run Code Online (Sandbox Code Playgroud)

我做了一个 SQL 列出了按最高分 (DESC) 和耗时 (ASC) 排序的前 50 名玩家,下面的 Sql 允许我获得每个谜题 ID 的结果。我不确定它是否是 100%,但我相信它是正确的。

;with ResultSet (PlayerID, maxScore, minTime, playedDate) 
AS
(
  SELECT TOP 50 PlayerID, MAX(score) as maxScore, MIN(timetaken) as minTime, MIN(datecreated) as playedDate
    FROM gameresult
    WHERE puzzleID = @PuzzleID
    GROUP BY PlayerID
    ORDER BY maxScore desc, minTime asc, playedDate asc
)
SELECT RSP.[PlayerID], RSP.[PlayerName], RSA.maxScore, RSA.minTime, RSA.PlayedDate
FROM ResultSet RSA
INNER JOIN Player RSP WITH(NOLOCK) 
    ON RSA.PlayerID = RSP.PlayerID
ORDER BY 
    maxScore DESC, 
    minTime ASC,
    playedDate ASC
Run Code Online (Sandbox Code Playgroud)

1)我需要修改SQL来做3个拼图ID的累积排名。例如,拼图 1、2、3 应该按照最高总分 (DESC) 和总耗时 (ASC) 排序

2) 我还需要所有可能的 1 到 7 谜题的总分。

3) 每个玩家只允许出现一次。首先播放并首先获得最高分将排名第一。

我尝试将 CTE 与 UNION 一起使用,但 SQL 语句不起作用。

我希望这里的大师可以帮助我解决这个问题。非常感激。

Jon*_*gel 5

好的,这是修改后的查询以按您想要的方式工作:

DECLARE @players table
(
    PlayerID uniqueidentifier NOT NULL PRIMARY KEY,
    PlayerName nvarchar(64) NOT NULL
);

DECLARE @playerScores table
(
    ID bigint NOT NULL IDENTITY PRIMARY KEY,
    PlayerID uniqueidentifier NOT NULL,
    DateCreated datetime NOT NULL,
    Score int NOT NULL,
    TimeTaken bigint NOT NULL,
    PuzzleID int NOT NULL
);

DECLARE @puzzleId int = 0;

SELECT TOP 50
    a.PlayerID,
    p.PlayerName,
    a.Score,
    a.TimeTaken,
    a.PlayedDate
    FROM
    (
        SELECT
            ps.PlayerID,
            ps.Score,
            ps.TimeTaken,
            ps.DateCreated AS PlayedDate,
            ROW_NUMBER()
                OVER
                (
                    PARTITION BY ps.PlayerID
                    ORDER BY ps.Score DESC, ps.TimeTaken, ps.DateCreated
                ) AS RN
            FROM @playerScores ps
            WHERE ps.PuzzleID = @puzzleId
    ) a
    INNER JOIN @players p ON p.PlayerID = a.PlayerID
    WHERE a.RN = 1
    ORDER BY
        a.Score DESC,
        a.TimeTaken,
        a.PlayedDate;
Run Code Online (Sandbox Code Playgroud)

写完这个(注意:索引没有优化),看看你需要写的其他查询,我实际上建议的是完全放弃这种类型的查询,并创建一个非规范化的高分表(行在PlayerID, PuzzleID)的组合上是唯一的,在其上运行聚合。

原因是因为该GameResult表将在数据库中变得巨大,因此随着时间的推移直接在其上运行聚合的效率会越来越低,并且要求与执行诸如创建索引视图以进行汇总之类的操作不兼容信息。

此外,如果您还没有这样做,您很可能希望使用异步过程来定期计算“排行榜”并缓存结果,而不是及时计算它们。(你可以做一些事情,比如将当前玩家的分数与缓存的排行榜合并,这样如果玩家获得高分,他们就可以立即在排行榜上看到自己。)在实现缓存机制时,请参阅我的回答这里的一些想法。