这个查询可能吗?

时间:2010-08-10 00:26:40

标签: database mysql

提前抱歉进行大量查询。我一直在努力,不能为我的生活让这个查询工作。当两个登录用户互相对战时,它会为两个用户增加输赢。 (这是石头剪刀)。我可以让它适用于单个用户,但是当我尝试收集对用户进行总结的“统计表”时,我得到了重复。

这是我的缩写为简洁架构

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
祝你好运,谢谢!

2 个答案:

答案 0 :(得分:0)

目前,您的桌面设计未正确规范化 - 您将始终拥有与每个rps_session和rps_game记录相关联的两个不同的玩家。根据我的选择,我会对这些进行规范化,以便在它们和rps_user表之间有一个链接表。

话虽如此,你很有可能无法做到这一点,所以有一个简单的答案:简单地将第二个查询中的胜利,损失和关系数字除以2.这应该始终有效,就像每一个一个用户是user1,另一个用户是user2的游戏 - 这就是你看到双倍值的原因。

NB。如果您实际系统中三个表之间的关系比您在此处呈现的更复杂(因此您不能依赖每个游戏总共有两个用户),此解决方案将不可靠。

答案 1 :(得分: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的粉丝,希望你的环境语法正确。

祝你好运。