2017-05-25 43 views
0

所以数据库结构我是:什么是做到这一点的PHP/SQL的最快方法/排序

steamid | mapname | name | teleports | runtime | runetimepro | teleports_pro 

enter image description here

所以我需要做的是为每个地图我要图在运行该地图的其他玩家中排名。玩家可以运行protime(runtimepro)或正常时间(运行时)的地图。所以如果一个剧本同时拥有一个protime和一个正常的时间,那么我将不得不知道他的战绩和正常时间(他们彼此独立)。

我目前的做法是建立一个foreach循环遍历每个mapname,并将玩家的steamid,mapname和run type发送给一个函数,然后查询一个数据库。对于该代码是下面:

function getKZTimeRank($steamID, $map, $type, $dbkz){ 
    if($type == "Pro"){ 
     $stmt = "SELECT * From playertimes WHERE mapname = :mapname AND runtimepro <> -1 ORDER BY runtimepro DESC"; 
     $query = $dbkz->prepare($stmt); 
     $query->bindValue(":mapname", $map); 
     $query->execute(); 
     $items = $query->fetchAll(PDO::FETCH_ASSOC); 
     $count = 1; 
     foreach($items as $map){ 
      if ($map['steamid'] == $steamID){ 
       return $count; 
      }else{ 
       $count++; 
      } 
     } 
    }elseif($type == "TP"){ 
     $stmt = "SELECT * From playertimes WHERE mapname = :mapname AND runtime <> -1 ORDER BY runtime DESC"; 
     $query = $dbkz->prepare($stmt); 
     $query->bindValue(":mapname", $map); 
     $query->execute(); 
     $items = $query->fetchAll(PDO::FETCH_ASSOC); 
     $count = 1; 
     foreach($items as $map){ 
      if ($map['steamid'] == $steamID){ 
       return $count; 
      }else{ 
       $count++; 
      } 
     } 
    } 
} 

代码抓起只有我们正在寻找的地图和所有的时候该地图(无论是Pro或正常是由$type确定)并拉动那些降序排列。对于那些按地图分类的玩家,它将用计数器搜索蒸汽发生器,并返回其找到玩家的位置。这对于小数据集合起作用相当快,但我试图按地图列出玩家时间,并且在那里是几百张地图和几千名玩家。脚本需要一点时间才能运行,因为它需要为每个玩家运行的地图运行查询。有一个外部循环可以获取玩家跑过的所有地图,也可以获取地图的时间,然后该函数可以找出时间在其他时间的位置。例如,对于我的个人资料,我已经完成了190张地图,因此对于每张地图,它必须至少运行此功能1次。如果我有专业和正常的时间,一些地图需要运行两次。因此,最少我在最多380(加1)个查询中执行190个查询(加上1个外部查询)。这个脚本对我来说只需要6.5秒左右,但对于其他玩家来说,则需要12到15秒。有一个更好的方法吗?我已经看过array_multisort(),但我不确定这是否会有利于此项目。你能帮忙的话,我会很高兴。我是以最好的方式之一吗?如果事情不清楚,我可以尝试纠正任何混乱。

+0

好吧,如果你真的想知道,如果你认为的一个版本是优于另一个,只是实现它,看看每个版本需要多少毫秒(例如,运行一百次的平均值,然后除以一百) –

+0

以及地图表的结构是什么? –

+0

我想过multisort,但我仍在考虑如何实际执行它。我知道我将不得不按照mapname和protime/normal时间排序,但是我仍然试图想到其他循环,以确保我保留在我正在查看的特定映射以及其他一些细节中。仍试图找出该方法的后勤。 – AndyPet74

回答

0

也许有一两件事你可以尝试是这样的:

获取所有的一个玩家的信息:

SELECT * FROM playertimes WHERE steamid = :steamid and mapname = :mapname 

然后你就可以在每次倍,是玩家的时间之前数:

SELECT COUNT(*) as aggregate From playertimes WHERE mapname = :mapname AND runtimepro <> -1 AND runtimepro < :runtimepro 

然后你有一个玩家的排名:

$item = $query->fetch(); 
$rank = $item->aggregate; 

同样可以正常运行

我认为它会工作要做,但我不知道这是否会走得更快

相关问题