1

我正在用 PHP/MySQL 构建一个运动系统。在 StackOverFlow 的一些帮助下,我构建了它。

我有 OW_SPORTS_GAMES 表,其中包含有关使用团队 ID 和分数进行的每场比赛的所有详细信息。这是结构。

在此处输入图像描述

还有另一个表 OW_SPORTS_PREDICTIONS 存储用户对游戏结果的预测。用户可以预测哪支球队将赢得比赛。这是表结构。

在此处输入图像描述

我希望得到结果,我可以知道每个用户做出了多少正确和错误的预测。如果猜对了,用户将获得每场比赛的积分(积分列)。输出应忽略双方得分均为 0 的任何比赛。

这是我当前的 SQL:

SELECT p.userId,
       SUM(IF(g.id IS NOT NULL, 1, 0)) correct,
       SUM(IF(g.id IS NULL, 1, 0)) wrong,
       SUM(IF(g.id IS NOT NULL, g.points, 0)) AS points
  FROM
       (SELECT * FROM ow_sports_games WHERE seasonId = 10 AND (homeTeamScore > 0 OR awayTeamScore > 0) ) g
  RIGHT JOIN ow_sports_predictions p
     ON g.id = p.gameId
    AND p.teamId = IF(g.homeTeamScore > g.awayTeamScore , g.homeTeam, IF(g.homeTeamScore < g.awayTeamScore , g.awayTeam, NULL))
  GROUP BY p.userId ORDER BY points DESC, correct DESC, wrong DESC;

使用此 SQL,我得到了错误的统计数据,其中还考虑了用户未预测的游戏和得分 0-0。

SQL 小提琴:http ://sqlfiddle.com/#!2/f4c9ed/2

在同一个小提琴数据中,应该是 2 个正确和 2 个错误的预测。但它有 2 个正确和 4 个错误的预测。

4

4 回答 4

1

您的问题是您将 JOIN 限制为仅返回预测正确的游戏;

AND p.teamId = IF(g.homeTeamScore > g.awayTeamScore , g.homeTeam, IF(g.homeTeamScore < g.awayTeamScore , g.awayTeam, NULL))

但是,您在计算错误预测数量时的假设是游戏 id 将为空:

SUM(IF(g.id IS NULL, 1, 0)) wrong,

0-0但是,如果分数是您试图排除的分数,则游戏 ID 也将为空。我会简化这一点,首先通过简化连接条件,这样您就可以切换到 INNER JOIN:

SELECT  *
FROM    ow_sports_predictions p
        INNER JOIN ow_sports_games g
            ON g.id = p.gameId
WHERE   g.SeasonID = 10

然后您可以确定预测是否正确的逻辑(这比我稍后将使用的更详细,但更好地展示了逻辑),

SELECT  *,
        CASE WHEN g.homeTeamScore > g.awayTeamScore AND g.HomeTeam = p.TeamID THEN 'Correct - Home Win'
            WHEN g.awayTeamScore > g.homeTeamScore AND g.AwayTeam = p.Teamid THEN 'Correct - Away Win'
            WHEN g.homeTeamScore + g.awayTeamScore = 0 THEN 'Void (0-0)'
            ELSE 'Lose'
        END AS Result
FROM    ow_sports_predictions p
        INNER JOIN ow_sports_games g
            ON g.id = p.gameId
WHERE   g.SeasonID = 10;

最后,我们可以总结一下:

SELECT  p.userID,
        SUM(IF((g.homeTeamScore > g.awayTeamScore AND g.HomeTeam = p.TeamID) 
            OR (g.awayTeamScore > g.homeTeamScore AND g.AwayTeam = p.TeamID), 1, 0)) AS Correct,
        SUM(IF((g.homeTeamScore < g.awayTeamScore AND g.HomeTeam = p.TeamID) 
            OR (g.awayTeamScore < g.homeTeamScore AND g.AwayTeam = p.TeamID), 1, 0)) AS Wrong,
        SUM(IF((g.homeTeamScore > g.awayTeamScore AND g.HomeTeam = p.TeamID) 
            OR (g.awayTeamScore > g.homeTeamScore AND g.AwayTeam = p.TeamID), g.Points, 0)) AS Points,
        COUNT(*) AS TotalPredictions
FROM    ow_sports_predictions p
        INNER JOIN ow_sports_games g
            ON g.id = p.gameId
WHERE   g.SeasonID = 10
GROUP BY p.UserID;

SQL Fiddle 示例

于 2013-10-30T18:45:29.647 回答
1

我认为您的问题的主要根源是在加入预测时使用 RIGHT 连接 - 这将为您提供您不想计算的游戏的数据行...尝试将其更改为 LEFT 连接并让我们知道.

更新:因为指出 RIGHT 加入正在提取额外记录而被否决?还有其他问题,但我认为这是最大的问题。因为显然我应该提供一个完整的答案,所以这是我将使用的一个查询,并附有小提琴:

http://sqlfiddle.com/#!2/f4c9ed/49

SELECT s.userId,
  SUM(IF(s.teamId = s.winningTeam, 1, 0)) correct,
  SUM(IF(s.teamId != s.winningTeam, 0, 1)) wrong,
  SUM(IF(s.teamId = s.winningTeam, s.points, 0)) points
FROM
  (SELECT p.*, g.points,
   IF (g.homeTeamScore-g.awayTeamScore > 0, g.homeTeam, g.awayTeam) as winningTeam
   FROM ow_sports_predictions p
    INNER JOIN ow_sports_games g ON g.id = p.gameId AND g.homeTeamScore+g.awayTeamScore > 0) s
GROUP BY s.userId;
于 2013-10-30T18:26:28.387 回答
1

这是我的,它给你答案。

select sp.userid,
       sum(if ( (sp.teamid = sg.idwinner), 1, 0 )) correct,
       sum(if ( (sp.teamid != sg.idwinner), 0, 1)) wrong,
       sum(if ( (sp.teamid = sg.idwinner), sg.points, 0 )) points
  from (select if ( homeTeamScore>awayTeamScore, homeTeam, awayTeam ) idwinner,
               sg.* 
         from ow_sports_games sg
        where homeTeamScore>0 and awayTeamScore>0 ) sg,
       ow_sports_predictions sp
 where sg.id = sp.gameid
 group by sp.userid

修改您的数据,其中一些点发生了变化。

于 2013-10-30T19:01:57.960 回答
0

这是一个快速变体,它计算每个用户的所有数字,当然你只需要其中的 2 个,计算第 3 个就足够了:

select
  b.userId,
  count(*) as total_predictions,
  sum(if(b.teamId=q.winteam,1,0)) as correct_predictions,
  sum(if(b.teamId<>q.winteam,1,0)) as wrong_predictions
from ow_sports_predictions as b
inner join
(
select
a.id,
if (a.hometeamscore>a.awayteamscore, a.hometeam, if(a.hometeamscore<a.awayteamscore, a.awayteam, -1)) as winteam
from ow_sports_games as a
)
as q
on (b.gameId=q.id)
group by b.userId;

这是简化版本:

select
  b.userId,
  count(*) as total_predictions,
  sum(if(b.teamId=if (q.hometeamscore>q.awayteamscore, q.hometeam, if(q.hometeamscore<q.awayteamscore, q.awayteam, -1)),1,0)) as correct_predictions
from ow_sports_predictions as b
inner join ow_sports_games as q
on (b.gameId=q.id)
group by b.userId;

要计算积分,您需要更改1IFpoints例如:

select
  b.userId,
  count(*) as total_predictions,
  sum(if(b.teamId=if (q.hometeamscore>q.awayteamscore, q.hometeam, if(q.hometeamscore<q.awayteamscore, q.awayteam, -1)),q.points,0)) as correct_predictions_mul_points
from ow_sports_predictions as b
inner join ow_sports_games as q
on (b.gameId=q.id)
group by b.userId;
于 2013-10-30T18:18:14.307 回答