0

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

这是我的数据库结构

表:播放器

PlayerID uniqueIdentifier (PK)
PlayerName nvarchar

表:游戏结果

ID bigint (PK - Auto Increment)
PlayerID uniqueIdentifier (FK)
DateCreated Datetime
Score int
TimeTaken bigint
PuzzleID int

我已经完成了一个 SQL 列出了按最高分 (DESC) 和耗时 (ASC) 排序的前 50 名球员

WITH ResultSet (PlayerID, Score, TimeTaken) AS(
  SELECT DISTINCT(A.[PlayerID]), MAX(A.[Score]),MIN(A.[TimeTaken])
  FROM GameResult A
  WHERE A.[puzzleID] = @PuzzleID
  GROUP BY A.[PlayerID])
SELECT TOP 50 RSP.[PlayerID], RSP.[PlayerName], RSA.[Score], RSA.[TimeTaken]
FROM ResultSet RSA
INNER JOIN Player RSP WITH(NOLOCK) ON RSA.PlayerID = RSP.PlayerID
ORDER By RSA.[Score] DESC, RSA.[timetaken] ASC

然而,以上仅适用于 1 个谜题。

问题

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

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

3) 每个玩家只允许出现在列表中一次。最先玩和最先获得最高分的将排名第一。

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

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

使用新 SQL 更新

下面的 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
4

1 回答 1

3

我首先要指出的是,我不相信您的原始查询是正确的。如果您正在为特定谜题寻找最佳玩家,那是最高分加上该谜题的最佳时间的组合吗?如果是,使用 max 和 min 并不能保证 max 和 min 来自同一个游戏(或行),我认为这应该是一个要求。相反,您应该首先使用行号窗口函数确定每个玩家的最佳游戏。然后,您可以对该数据进行前 50 位排序。

累积指标应该更容易计算,因为您只需汇总他们的分数总和和他们的时间总和然后排序,这意味着新查询很可能看起来像这样:

;with ResultSet (PlayerID, Score, TimeTaken) 
AS
(
SELECT TOP 50 
    A.[PlayerID], 
    SUM(A.[Score]),
    SUM(A.[TimeTaken])
FROM GameResult  A
WHERE 
    A.[puzzleID] in(1,2,3)
GROUP BY 
    A.PlayerID
ORDER BY 
    SUM(A.[Score]) DESC,
    SUM(A.[TimeTaken]) ASC
)
SELECT RSP.[PlayerID], RSP.[PlayerName], RSA.[Score], RSA.[TimeTaken]
FROM ResultSet RSA
INNER JOIN Player RSP WITH(NOLOCK) 
    ON RSA.PlayerID = RSP.PlayerID
ORDER BY 
    Score DESC, 
    TimeTaken ASC

更新:

根据新标准,您将不得不做这样的事情。

;WITH ResultSet (PlayerID, PuzzleId, Score, TimeTaken, seq) 
AS
(
SELECT
    A.[PlayerID], 
    A.PuzzleID,
    A.[Score],
    A.[TimeTaken],
    seq = ROW_NUMBER() over(PARTITION BY PlayerID, PuzzleId ORDER BY Score DESC)
FROM GameResult A
WHERE 
    A.[puzzleID] in(1,2,3)
)
SELECT TOP 50
    RSP.[PlayerID], 
    RSP.[PlayerName], 
    Score = SUM(RSA.[Score]), --total score
    TimeTaken = SUM(RSA.[TimeTaken]) --total time taken
FROM ResultSet RSA
INNER JOIN Player RSP 
    ON RSA.PlayerID = RSP.PlayerID
WHERE
    --this is used to filter the top score for each puzzle per player
    seq = 1
GROUP BY
    RSP.[PlayerID], 
    RSP.[PlayerName]
ORDER BY
    SUM(RSA.Score) DESC,
    SUM(RSA.TimeTaken) ASC
于 2013-06-27T16:44:32.227 回答