2012-07-31 37 views
3

我有一個高分表scores: (id int, deviceid int, value int, board int)。 我想顯示特定玩家的位置。目前,我這樣做(在PHP):MySQL - 獲取計數()爲不同條件組中的每一行

我選擇,玩家有一個分值和評分本身的所有板:

select board, min(value) as value 
from scores 
where deviceid = 1234 
group by board 

然後每行($板,$值)我選擇:用分數小於規定值選擇行數爲特定的板

select count(id) from scores 
where board = $board and value < $value 

,我得到了玩家的位置(第一玩家將獲得0位置,因此顯示時將增加1)

我知道這太可怕了,所以我正在尋找一種的方式來更快地完成它。它可以在存儲過程中使用遊標完成,但對於100個板卡,我最多需要執行1 + 100次選擇。

我概括地說,我願做這樣的事情,在僞SQL:

select board, min(value) as val, 
     count(id) from _this_group_ where value < val 
from scores 
where deviceid = 1234 
group by board 

回答

2
SELECT scores.board, count(1) AS position 
FROM scores 
JOIN 
    (SELECT board, MIN(value) AS value 
    FROM scores 
    WHERE deviceid = 1234 
    GROUP BY board 
) player_scores 
ON scores.board = player_scores.board 
WHERE scores.value < player_scores.value 
GROUP BY scores.board 
+0

謝謝,我剛剛添加了scores.board專欄來首先選擇,所以我會知道哪個b oard也是 – Axarydax 2012-07-31 11:56:53

+0

的選定分數,有沒有辦法避免掃描數據庫中的所有行?如果我有1 000 000行,mysql解釋這個查詢說它經歷了1 000 000行。 – Axarydax 2012-07-31 12:22:04

+1

(deviceid)上的索引將加速子查詢。 (board,value)上的索引可能會加速外部查詢,但在最壞的情況下(玩家在所有主板上得分最高),它仍然需要經過幾乎所有的行。 – 2012-07-31 12:47:44

0

你可以嘗試這樣的:

SELECT a.board, b.val COUNT(1) AS cnt 
FROM scores a 
    INNER JOIN(
     SELECT board, MIN(value) as val 
     FROM scores 
     WHERE deviceid = 1234 
     GROUP BY board 
    ) b 
    ON a.board = b.board 
    AND a.value < b.val 
WHERE a.deviceid = 1234 
GROUP BY a.board; 

SELECT a.board, MIN(a.value) as val, 
     (SELECT COUNT(1) 
     FROM scores b 
     WHERE b.board = a.board AND 
     b.value < MIN(a.value)) AS cnt 
FROM scores a 
WHERE a.deviceid = 1234; 
相關問題