我一直在开设一个显示评级阶梯的网站,它会处理玩家所玩的所有比赛。
我目前所拥有的是下表,但是当我想选择玩家的所有匹配时,我必须包含“或”语句,并且还具有所有具有玩家名称的列的索引。所以我设计了一种新方法。
[当前方法]
aoe3_sp_games表
信息:保留所有比赛以及与之相关的球员。
Column Type Null Default
game_id char(36) No
map varchar(30) No
date_time int(11) No
length float No
player_count tinyint(4) No
t1_p1 varchar(16) No
t1_p2 varchar(16) No
t1_p3 varchar(16) No
t1_p4 varchar(16) No
t2_p1 varchar(16) No
t2_p2 varchar(16) No
t2_p3 varchar(16) No
t2_p4 varchar(16) No
t1_p1_rating smallint(4) No
t1_p2_rating smallint(4) No
t1_p3_rating smallint(4) No
t1_p4_rating smallint(4) No
t2_p1_rating smallint(4) No
t2_p2_rating smallint(4) No
t2_p3_rating smallint(4) No
t2_p4_rating smallint(4) No
t1_p1_pr float(6,2) No
t1_p2_pr float(6,2) No
t1_p3_pr float(6,2) No
t1_p4_pr float(6,2) No
t2_p1_pr float(6,2) No
t2_p2_pr float(6,2) No
t2_p3_pr float(6,2) No
t2_p4_pr float(6,2) No
t1_p1_civ char(2) No
t1_p2_civ char(2) No
t1_p3_civ char(2) No
t1_p4_civ char(2) No
t2_p1_civ char(2) No
t2_p2_civ char(2) No
t2_p3_civ char(2) No
t2_p4_civ char(2) No
[新方法]
aoe3_sp_matches表
信息:保留所有比赛。
Column Type Null Default
match_id int(10) No
match_guid char(36) No
map varchar(30) No
date_time int(11) No
length float No
player_count tinyint(4) No
aoe3_sp_match_players表
信息:保留与#Matches_table相关的所有与比赛相关的球员。
Column Type Null Default Links to
match_id int(10) No aoe3_sp_matches -> match_id
player_id int(10) No eso_players -> player_id
team tinyint(4) No
player_name varchar(16) No
player_rating smallint(4) No
player_pr float(6,2) Yes NULL
player_civ char(2) No
我需要的是使用#Match_Players_table获取玩家所玩的所有比赛。 然后将比赛ID加入参与比赛的球员。
任何比赛最多只能有8名玩家(4vs4)和至少2名(1vs1)玩家。
我正在使用Player 1570进行测试,因为他看起来很适合没有太多比赛的情况。
我已经阅读过某个地方,不要使用不超过2个连接,否则它可能会对性能造成不良影响。 我的网站处理大约5000场比赛3天,17000行处理玩家,这些数字基于新方法。
我的mysql版本是:5.1.61。
我的网站 :http://exciple.com/forum/player.php?n=yosimasa&s=m
SQL小提琴 :http://sqlfiddle.com/#!2/0b2245/3
结果类型
基本上将一行中属于该比赛的所有球员与比赛信息相结合,就像方法一一样。我确实试图得到这样的结果,但我努力加入不止一个连接的连接。我知道这需要很多连接,所以不是理想的方法。
game_id map date_time length player_count t1_p1 t1_p2 t1_p3 t1_p4 t2_p1 t2_p2 t2_p3 t2_p4 t1_p1_rating t1_p2_rating t1_p3_rating t1_p4_rating t2_p1_rating t2_p2_rating t2_p3_rating t2_p4_rating t1_p1_pr t1_p2_pr t1_p3_pr t1_p4_pr t2_p1_pr t2_p2_pr t2_p3_pr t2_p4_pr t1_p1_civ t1_p2_civ t1_p3_civ t1_p4_civ t2_p1_civ t2_p2_civ t2_p3_civ t2_p4_civ
43f9499f-870d-47c0-8a05-47554e349698 great plains 1413510540 1451 4 greenandugly Jomp17 Armykid913 FUHAHAHA 1616 1616 0 0 1584 1571 0 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 FR OT OT BR
结果类型二
所以我一直在搞乱查询,这是我到目前为止所做的。
执行两个查询
[游戏一个]
SELECT aoe3_sp_matches.* FROM aoe3_sp_matches
right JOIN `aoe3_sp_match_players`
ON `aoe3_sp_match_players`.`match_id`=`aoe3_sp_matches`.`match_id`
WHERE player_id = 1570
返回播放器1570的所有游戏。这样可以正常工作。
[第二场比赛的球员]
SELECT aoe3_sp_match_players.* FROM aoe3_sp_match_players
right JOIN `aoe3_sp_matches`
ON `aoe3_sp_match_players`.`match_id`=`aoe3_sp_matches`.`match_id`
WHERE aoe3_sp_match_players.player_id = 1570
返回符合where子句的aoe3_sp_match_players中的数据。不返回所有玩家,只返回where子句中的一个。
SELECT aoe3_sp_match_players.* FROM aoe3_sp_match_players
WHERE aoe3_sp_match_players.match_id in
(SELECT aoe3_sp_match_players.match_id
FROM aoe3_sp_match_players
WHERE player_id = 1570)
我设法以我想要的方式获取数据但是使用子查询并且它比我的数据库中的连接慢,而不是在那里出现。
编辑: 我找到了一种方法,可以在外部使用连接获取结果类型2的第二部分,它与放在之前的连接一样快子句。
Select
aoe3_sp_match_players.match_id,
aoe3_sp_match_players.team,
aoe3_sp_match_players.player_name,
aoe3_sp_match_players.player_rating,
aoe3_sp_match_players.player_pr,
aoe3_sp_match_players.player_civ
From
(Select
aoe3_sp_match_players.match_id
From
aoe3_sp_match_players
Where
aoe3_sp_match_players.player_id = 1570
Limit 30) aoe3_sp_matches Left Join
aoe3_sp_match_players On aoe3_sp_match_players.match_id =
aoe3_sp_matches.match_id
Order By
aoe3_sp_match_players.match_id Desc
您认为获得结果的最佳方法是什么?
答案 0 :(得分:0)
此设置存在问题。你的新方法肯定比上一个好,但它仍然需要一些解决方法。你虽然走在了正确的轨道上。
每场比赛允许的球员数量是否有限制?看起来你的旧方法允许每场比赛最多4名球员。在你的新方法中,你可以在每场比赛中拥有任意数量的球员,这可能是也可能不是你想要的。
只有在您的应用程序中强制执行最多四名玩家才能分享匹配项时,才能实现您期望的结果。但这并不合适,因为您的数据完整性现在取决于应用程序层而不仅仅是数据库。
如果不考虑我提到的所有这些事情,你可以这样做:
SELECT
game.match_id,
game.match_guid,
game.map,
game.date_time,
game.length,
game.player_count,
team1_player1.player_name,
team1_player1.player_rating,
team1_player1.player_pr,
team1_player1.player_civ,
team1_player2.player_name,
team1_player2.player_rating,
team1_player2.player_pr,
team1_player2.player_civ,
team1_player3.player_name,
team1_player3.player_rating,
team1_player3.player_pr,
team1_player3.player_civ,
team1_player4.player_name,
team1_player4.player_rating,
team1_player4.player_pr,
team1_player4.player_civ,
team2_player1.player_name,
team2_player1.player_rating,
team2_player1.player_pr,
team2_player1.player_civ,
team2_player2.player_name,
team2_player2.player_rating,
team2_player2.player_pr,
team2_player2.player_civ,
team2_player3.player_name,
team2_player3.player_rating,
team2_player3.player_pr,
team2_player3.player_civ,
team2_player4.player_name,
team2_player4.player_rating,
team2_player4.player_pr,
team2_player4.player_civ
FROM
matches_table as game
LEFT JOIN match_players as team1_player1 ON game.match_id = team1_player1.match_id and team1_player1.player_id = 1
LEFT JOIN match_players as team1_player2 ON game.match_id = team1_player2.match_id and team1_player1.player_id = 2
LEFT JOIN match_players as team1_player3 ON game.match_id = team1_player3.match_id and team1_player1.player_id = 3
LEFT JOIN match_players as team1_player4 ON game.match_id = team1_player4.match_id and team1_player1.player_id = 4
LEFT JOIN match_players as team2_player1 ON game.match_id = team2_player1.match_id and team1_player1.player_id = 5
LEFT JOIN match_players as team2_player2 ON game.match_id = team2_player2.match_id and team1_player1.player_id = 6
LEFT JOIN match_players as team2_player3 ON game.match_id = team2_player3.match_id and team1_player1.player_id = 7
LEFT JOIN match_players as team2_player4 ON game.match_id = team2_player4.match_id and team1_player1.player_id = 8
你必须先了解球员的ids。此外,玩家只能连接到一场比赛。对于新的比赛,这个值必须改变,我们会放弃玩家所处的任何先前比赛的历史。这是为了说明它可以完成,以及它可以获得多么丑陋。我不建议以这种方式进行。
请注意,您可以多次加入同一张桌子。这可能非常有用,因为您需要将许多记录中的信息压缩为一个。
<强> SOLUTION:强>
你可以有一个游戏桌,一个玩家桌子,并为比赛创建第三个桌子:
<强>游戏强>
game_id
map
//other columns with info about this map. you could also name the table maps
<强>球员强>
player_id
player_name
player_pr
player_civ
<强>匹配强>
match_id
map
date_time
team1_player1
team1_player2
team2_player1
team2_player2
这最后一个表包含了玩家的ID。输出可能如下所示:
match_id map team1_player1 team1_player2 team2_player1 team2_player2
1 great plains 0001 0002 0003 0004
您还可以将用户名用作ID,只需确保它们是唯一的(主键)
生成的SQL查询将是这样的:
SELECT
games.map,
matches.match_id,
matches.date_time,
team1_player1.player_name,
team1_player1.player_rating,
team1_player1.player_pr,
team1_player1.player_civ,
team1_player2.player_name,
team1_player2.player_rating,
team1_player2.player_pr,
team1_player2.player_civ,
team1_player3.player_name,
team1_player3.player_rating,
team1_player3.player_pr,
team1_player3.player_civ,
team1_player4.player_name,
team1_player4.player_rating,
team1_player4.player_pr,
team1_player4.player_civ,
team2_player1.player_name,
team2_player1.player_rating,
team2_player1.player_pr,
team2_player1.player_civ,
team2_player2.player_name,
team2_player2.player_rating,
team2_player2.player_pr,
team2_player2.player_civ,
team2_player3.player_name,
team2_player3.player_rating,
team2_player3.player_pr,
team2_player3.player_civ,
team2_player4.player_name,
team2_player4.player_rating,
team2_player4.player_pr,
team2_player4.player_civ
FROM
games
INNER JOIN matches ON matches.map = games.map
INNER JOIN match_players as team1_player1 ON team1_player1.player_id = matches.team1_player1
INNER JOIN match_players as team1_player2 ON team1_player1.player_id = matches.team1_player2
INNER JOIN match_players as team1_player3 ON team1_player1.player_id = matches.team1_player3
INNER JOIN match_players as team1_player4 ON team1_player1.player_id = matches.team1_player4
INNER JOIN match_players as team2_player1 ON team1_player1.player_id = matches.team2_player1
INNER JOIN match_players as team2_player2 ON team1_player1.player_id = matches.team2_player2
INNER JOIN match_players as team2_player3 ON team1_player1.player_id = matches.team2_player3
INNER JOIN match_players as team2_player4 ON team1_player1.player_id = matches.team2_player4
通过这种方法,您的玩家表格仅包含有关玩家的信息,而不包含有关匹配的信息。您可以保留玩家所处的每场比赛的历史记录,并且您还可以将与比赛相关的地图和其他信息与比赛本身分开。匹配表只将所有内容联系在一起。此外,玩家编号限制返回到数据库并且与应用程序无关。
希望它有所帮助。