2010-08-10 152 views
1

對不起,提前大量查詢。我一直在努力,不能爲我的生活得到這個查詢工作。當兩個登錄用戶互相對戰時,這會爲兩位用戶增加贏家和輸家。 (這是石頭剪刀)。我可以讓它爲單個用戶工作,但是當我嘗試收集用戶的「統計表」時,我得到了重複。這個查詢可能嗎?

這裏是我的簡稱換了 - 清酒的,簡潔模式

create table rps_user (
    user_id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    username VARCHAR(255), 
    PRIMARY KEY (user_id), 
    UNIQUE (username) 
); 

CREATE TABLE rps_session (
    session_id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    player1_user_id INT UNSIGNED DEFAULT NULL, 
    player2_user_id INT UNSIGNED DEFAULT NULL, 
    connected BOOLEAN DEFAULT 0, 
    PRIMARY KEY (session_id) 
); 

CREATE TABLE rps_game (
    game_id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    game_number INT UNSIGNED DEFAULT NULL, 
    session_id INT UNSIGNED NOT NULL, 
    player1_choice ENUM('ROCK','PAPER','SCISSORS') DEFAULT NULL, 
    player2_choice ENUM('ROCK','PAPER','SCISSORS') DEFAULT NULL, 
    PRIMARY KEY (game_id) 
); 

這裏是我的查詢工作

SELECT IF((player1_choice + 1) % 3 + 1 = player2_choice + 0 AND player1_user_id = rps_user.user_id OR 
     (player2_choice + 1) % 3 + 1 = player1_choice + 0 AND player2_user_id = rps_user.user_id, 1, 0) AS win, 
    IF(player1_choice = player2_choice, 1, 0) as tie, 
    IF(player1_choice % 3 + 1 = player2_choice + 0 AND player1_user_id = rps_user.user_id OR 
     player2_choice % 3 + 1 = player1_choice + 0 AND player2_user_id = rps_user.user_id, 1, 0) AS loss 
    FROM rps_game INNER JOIN rps_session USING (session_id) 
    INNER JOIN rps_user ON rps_session.player1_user_id = rps_user.user_id OR rps_session.player2_user_id = rps_user.user_id 
    WHERE player1_choice IS NOT NULL AND player2_choice IS NOT NULL and rps_user.user_id = ? 

並且不

的一個
SELECT username, SUM(IF((player1_choice + 1) % 3 + 1 = player2_choice + 0 AND player1_user_id = rps_user.user_id OR 
     (player2_choice + 1) % 3 + 1 = player1_choice + 0 AND player2_user_id = rps_user.user_id, 1, 0)) AS wins, 
    SUM(IF(player1_choice = player2_choice, 1, 0)) AS ties, 
    SUM(IF(player1_choice % 3 + 1 = player2_choice + 0 AND player1_user_id = rps_user.user_id OR 
     player2_choice % 3 + 1 = player1_choice + 0 AND player2_user_id = rps_user.user_id, 1, 0)) AS losses 
    FROM rps_game INNER JOIN rps_session USING (session_id) 
    INNER JOIN rps_user ON rps_session.player1_user_id = rps_user.user_id OR rps_session.player2_user_id = rps_user.user_id 
    WHERE player1_choice IS NOT NULL AND player2_choice IS NOT NULL 
    GROUP BY user_id ORDER BY wins DESC 

祝你好運,謝謝你!

+1

您是否考慮過使用命令式編程語言? – Borealid 2010-08-10 00:37:32

+0

我有,並最終(更快,沒有解決方案)會。這真的是懶惰變成sql練習的結果。 – uzrbin 2010-08-10 23:45:54

回答

0

目前,您的表格設計未正確歸一化 - 您將始終有兩個不同的球員與每個rps_session和rps_game記錄相關聯。根據我的選擇,我會規範化這些,以便它們和rps_user表之間有一個鏈接表。

說了這麼多,你很有可能無法做到這一點,所以有一個簡單的答案:簡單地將第二個查詢中的勝利,損失和關係數字除以2.這應該始終有效,至於每個遊戲中一個用戶是user1,另一個用戶是user2 - 這就是爲什麼你看到double值。

注意:如果您實際系統中三個表格之間的關係比您在此處展示的內容更復雜(因此您不能依賴每個遊戲始終有兩個用戶),則此解決方案將不可靠。

+0

感謝您的回覆,不幸的是,是的; player1_user_id和player2_user_id是DEFAULT NULL,因爲你不需要登錄玩。 – uzrbin 2010-08-10 23:46:11

+0

是否有使用相同條件的連接表的解決方案? – uzrbin 2010-08-10 23:51:28

+0

@uzrbin:在你的第二個查詢中,你已經包含條件'WHERE player1_choice IS NOT NULL AND player2_choice IS NOT NULL' - 在該查詢中,每個遊戲總是應該有2個用戶。但是,如果這個查詢不是真實的系統反映,但是你可以依靠每個遊戲總是有1或2個玩家,那麼我建議改變你所有的SUM(IF(...,1,0) )'條件爲SUM(IF(...,IF(player1_user_id IS NULL OR player2_user_id IS NULL,1,0.5),0))'。 – 2010-08-11 11:50:39

0

我希望這有助於!

兩個主要方面:

1小,易於理解,易於以後更改

2-大,更復雜,更難以改變!

讓我們先試試容易的:

create view stats as 
YOUR_FIRST_BIG_QUERY_HERE; 

現在很容易的路要走:

select USER_ID,sum(wins),sum(ties), sum(loses) 
from stats /*this is our new created view*/ 
group by USER_ID; 

很容易!

現在雖然一個!

讓我們在這裏使用子查詢:

select USER_ID,sum(wins),sum(ties), sum(loses) 
from (SELECT IF((player1_choice + 1) % 3 + 1 = player2_choice + 0 AND player1_user_id = rps_user.user_id OR 
    (player2_choice + 1) % 3 + 1 = player1_choice + 0 AND player2_user_id = rps_user.user_id, 1, 0) AS win, 
IF(player1_choice = player2_choice, 1, 0) as tie, 
IF(player1_choice % 3 + 1 = player2_choice + 0 AND player1_user_id = rps_user.user_id OR 
    player2_choice % 3 + 1 = player1_choice + 0 AND player2_user_id = rps_user.user_id, 1, 0) AS loss 
FROM rps_game INNER JOIN rps_session USING (session_id) 
INNER JOIN rps_user ON rps_session.player1_user_id = rps_user.user_id OR rps_session.player2_user_id = rps_user.user_id 
WHERE player1_choice IS NOT NULL AND player2_choice IS NOT NULL) 
group by USER_ID; 

實際上這兩個兩個是一樣的!

但我想顯示第二個醜陋的,因爲它是更好的使用意見!

我是一名oracle粉絲,希望在您的環境中使用正確的語法。

祝你好運。