累积游戏得分SQL

时间:2013-06-27 16:05:29

标签: sql sql-server database database-design

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

这是我的数据库结构

表:玩家

PlayerID uniqueIdentifier (PK)
PlayerName nvarchar

表:GameResult

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

我已经完成了一个SQL列表,排名前50位的玩家按最高分(DESC)和timetaken(ASC)排序

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

1 个答案:

答案 0 :(得分: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

UPDATE:

根据新标准,你必须做这样的事情。

;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