2012-04-19 55 views
3

嗨,我試圖找出找到最大的連勝紀錄在我的表中的每個成員的一種方式。當桌子建成時,這從來沒有出現在計劃中,所以我爲什麼尋求幫助來實現這一目標。MySQL的 - 連勝

我的結構如下:

id player_id opponant_id  won  loss timestamp 

如果它是一個人的遊戲中,玩家ID是他們的ID。如果他們受到某人的挑戰,他們的id是opponant id,贏得的損失(1或0)與player_id有關。

我想找到每個用戶的最大連勝。

人對如何與當前的表結構做任何想法。

問候

編輯

下面是一些測試數據,其中id 3是玩家的問題:

id player_id won  loss timestamp 
1 6   0  1  2012-03-14 13:31:00 
13 3   0  1  2012-03-15 13:10:40 
17 3   0  1  2012-03-15 13:29:56 
19 4   0  1  2012-03-15 13:37:36 
51 3   1  0  2012-03-16 13:20:05 
53 6   0  1  2012-03-16 13:32:38 
81 3   0  1  2012-03-21 13:14:49 
89 4   1  0  2012-03-21 14:01:28 
91 5   0  1  2012-03-22 13:14:20 
+0

我不認爲這可以用只有MySQL的代碼完成。我會做一個計算數據的cron腳本。 – cleanunicorn 2012-04-19 08:59:45

+1

什麼意思是「最大的連勝」? – 2012-04-19 09:02:57

+1

你有兩個記錄每個遊戲或只有一個?換句話說,如果opponant_id沒有相應的記錄,他們是player_id那麼你要算opponant_id /損失作爲該ID的勝利,對嗎? – davidethell 2012-04-19 09:03:34

回答

4

試試這個。 編輯,因爲它經過考慮到損失的行

SELECT 
    d.player_id, 
    MAX(d.winStreak) AS maxWinStreak 
FROM (
    SELECT 
     @cUser := 0, 
     @winStreak := 0 
) v, (

    SELECT 
     player_id, 
     won, 
     timestamp, 
     @winStreak := IF(won=1,IF(@cUser=player_id,@winStreak+1,1),0) AS winStreak, 
     @cUser := player_id 
    FROM (
     (
      -- Get results where player == player_id 
      SELECT 
       player_id, 
       won, 
       timestamp 
      FROM matchTable 
     ) UNION (
      -- Get results where player == opponent_id (loss=1 is good) 
      SELECT 
       opponent_id, 
       loss, 
       timestamp 
      FROM matchtable 
     ) 
    ) m 
    ORDER BY 
     player_id ASC, 
     timestamp ASC 
) d 
GROUP BY d.player_id 

這是通過選擇全贏/輸計數的連勝。子查詢然後按player_id進行分組,並按照循環計算的最大winStreak輸出爲每個玩家。

它似乎對我的測試數據集反正很好地工作:)

要做到這一點更有效地我會重組,即

matches (
    matchID, 
    winningPlayerID, 
    timeStamp 
) 

players (
    playerID 
    -- player name etc 
) 

matchesHasPlayers (
    matchID, 
    playerID 
) 

這將導致

SELECT 
    matches.matchID, 
    matchesHasPlayers.playerID, 
    IF(matches.winningPlayerID=matchesHasPlayers.playerID,1,0) AS won 
    matches.timestamp 
FROM matches 
INNER JOIN matchesHasPlayers 
ORDER BY matches.timestamp 
內查詢

產生於

SELECT 
    d.player_id, 
    MAX(d.winStreak) AS maxWinStreak 
FROM (
    SELECT 
     @cUser := 0, 
     @winStreak := 0 
) v, (
    SELECT 
     matchesHasPlayers.playerID, 
     matches.timestamp, 
     @winStreak := IF(matches.winningPlayerID=matchesHasPlayers.playerID,IF(@cUser=matchesHasPlayers.playerID,@winStreak+1,1),0) AS winStreak, 
     @cUser := matchesHasPlayers.playerID 
    FROM matches 
    INNER JOIN matchesHasPlayers 
    ORDER BY 
     matchesHasPlayers.playerID ASC, 
     matches.timestamp ASC 
) d 
GROUP BY d.player_id 
+0

這給出了一些有趣的結果,但它們不正確。這是否只考慮了玩家ID而不考慮opponant ID?如果opponant_id是有問題的用戶,並且是失敗的,那麼它與具有勝利的用戶相同 – 2012-04-19 09:33:13

+0

好的,所以對於player_id的「勝利」是=='player_id = xxx' AND'won = 1'或者'oppnent_id = xxx'和'lose = 1',如果是這樣的話,這感覺就像是一個不可靠的桌子設計,可以正常化,但它可以挽回 – 2012-04-19 09:48:16

+0

絕對geniussss! – 2012-04-19 10:08:31

0
SELECT * FROM 
(
    SELECT player_id, won, loss, timestamp 
    FROM games 
    WHERE player_id = 123 
    UNION 
    SELECT opponant_id as player_id, loss as won, won as loss, timestamp 
    FROM games 
    WHERE opponant_id = 123 
) 
ORDER BY timestamp 

這將會給大家一個球員的結果排序按時間戳。然後,您需要循環這些結果並計算獲勝記錄,否則將它們連接成一個字符串,然後使用字符串函數查找該字符串中最高的11111集。該代碼將根據您要使用的語言而有所不同,但從邏輯上講,這些是兩種選擇。

+0

啊,好吧,我是離開這作爲最後一個resourt,即時與PHP方便,但想看看是否可以用mysql的一個查詢,對於 – 2012-04-19 09:14:39

+1

你從一個臨時表在這裏選擇,讓'ORDER BY'將無法使用索引。這可能會讓sloooowwww擁有一個大型的遊戲桌。另外,也許這是我不知道的語法,但是'UNION'中的第二個'SELECT'不需要'FROM'子句? – Nanne 2012-04-19 09:18:55

+0

@Nanne,謝謝,修正了語法錯誤。你說得對,這對大數據集來說不會很快。 – davidethell 2012-04-19 09:26:17