2017-05-25 47 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; 

同樣可以正常運行

我認爲它會工作要做,但我不知道這是否會走得更快

相關問題