2010-08-10 108 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粉丝,希望在您的环境中使用正确的语法。

祝你好运。