用于跟踪头对头匹配记录的表设计?

时间:2012-01-10 00:41:36

标签: mysql database-design relational-database

我无法想出一个可行的表格设计来跟踪用户之间的头对头匹配结果。

所有用户都有UID。单个匹配结果存储在另一个表中,每个匹配都有自己的UID。

我想要的是能够通过简单的选择来提取这样的东西:

Player   vs.    Opponent   Wins   Losses   Draws
Bob             John       5      2        1
Bob             Sam        0      3        2
John            Bob        2      5        1

我可以通过PHP中的一些操作从原始匹配结果中提取这些数据,但它相当昂贵,所以我想使用cron作业并将这些“已完成”的统计信息存储在表中以便快速读取。

让我感到震惊的是,一个数据集(2个玩家,胜利,失败,平局计数)可以在两个方向上读取,具体取决于你想要的玩家的观点,如上面针对Bob和John所描述的。

我可以制作这样一张桌子:

[player]  [opponent]  [wins]  [losses]  [draws]

但是每个“set”都需要两行......

[player]  [opponent]  [wins]  [losses]  [draws]
bob       john        5       2         1
john      bob         2       5         1

并且重复似乎可能会在以后引起我的问​​题,虽然我无法想到原因,只是干,所有这些......

建议?

2 个答案:

答案 0 :(得分:1)

我看到你提到的重复方法有效使用了。只要你知道重复,就不会太难处理。

如果你想避免重复,你可能需要更多的代码和更多的代码复杂性:要显示单个玩家的所有结果,你需要找到该玩家的记录“玩家”或“对手”。

一个(我认为)有用的方式来报告所有玩家的记录(与他们的对手相比)将是两次显示每个“对战”记录 - 一次作为玩家,组合在一起,一次作为对手,在他们的对手的每组记录中:

Player   vs.    Opponent   Wins   Losses   Draws
Bob             John       5      2        1
Bob             Sam        0      3        2
John            Bob        2      5        1
John            Sam        1      2        1
Sam             Bob        3      0        2
Sam             John       2      1        1

答案 1 :(得分:1)

假设你有一个表(MatchID,Player1ID,Player2ID,Player1Score,Player2Score ......),每个匹配都有一个行(即没有重复)

您可以通过以下方式获取玩家的所有比赛:

SELECT * from Matches WHERE Player1ID = @ID OR Player2ID = @ID

可能稍微有用的是稍微重新排列数据,所以它总是玩家和对手:

SELECT MatchID, Player1ID, Player2ID, Player1Score, Player2Score ... FROM Matches where Player1ID = @ID
UNION
SELECT MatchID, Player2ID, Player1ID, Player2Score, Player1Score ... FROM Matches where Player2ID = @ID

(请注意,第二个联合声明中的ID和分数顺序都相反)

您还可以对统计数据构建进行概括:

 SELECT stats.Player, stats.Opponent, SUM(stats.PlayerWin) AS Wins, SUM(stats.Draw) AS Draws, SUM(stats.OpponentWin) AS Losses
 FROM (
    SELECT Player1ID AS Player, Player2ID AS Opponent, 
        CASE WHEN Player1Score > Player2Score THEN 1 ELSE 0 END AS PlayerWin,
        CASE WHEN Player1Score = Player2Score THEN 1 ELSE 0 END AS Draw, 
        CASE WHEN Player2Score > Player1Score THEN 1 ELSE 0 END AS OpponentWin
    UNION
    SELECT Player2ID AS Player, Player1ID AS Opponent, 
        CASE WHEN Player2Score > Player1Score THEN 1 ELSE 0 END AS PlayerWin,
        CASE WHEN Player2Score = Player1Score THEN 1 ELSE 0 END AS Draw, 
        CASE WHEN Player1Score > Player2Score THEN 1 ELSE 0 END AS OpponentWin
     ) stats
 GROUP BY stats.Player, stats.Opponent

我想我的一般观点是你可以用任何一种方式,它们大致同样复杂(如果你将数据放入数据库两次,你必须确保在更新它时保持同步。如果你把数据进入数据库一次,你在进行统计数据时必须计算两次。另外,如果你将数据放入数据库两次,那么数据库方面会有一些问题变得复杂,因为MatchID将不再是唯一的。)