计算多个表中的行

时间:2009-10-20 04:28:40

标签: sql mysql

我有一个跟踪曲棍球统计数据的mysql数据库。我想做的是在一个查询中获取每个玩家得分的目标和助攻的数量以及他们玩过的游戏数量。我正在使用Zend Framework和我构建的查询是这样的:

SELECT `p`.*, 
       `pxt`.`jersey_number`, 
       count(pxg.player_x_game_id) AS `games`, 
       count(goals.scoring_id) AS `goals`, 
       count(assists.scoring_id) AS `assists` 
FROM  `players` AS `p` 
INNER JOIN `players_x_teams` AS `pxt` ON p.player_id = pxt.player_id 
INNER JOIN `teams_x_seasons` AS `txs` ON pxt.team_id = txs.team_id 
INNER JOIN `seasons` AS `s` ON txs.season_id = s.season_id 
INNER JOIN `games` AS `g` ON g.season_id = s.season_id
INNER JOIN `players_x_games` AS `pxg` ON pxg.game_id = g.game_id 
                                     AND pxg.player_id = p.player_id 
LEFT JOIN `scoring` AS `goals` ON goals.game_id = g.game_id 
                              AND goals.scorer_id = p.player_id 
LEFT JOIN `scoring` AS `assists` ON assists.game_id = g.game_id 
                                AND (assists.assist1_id = p.player_id OR assists.assist2_id = p.player_id) 
WHERE (pxt.team_id = 1) 
  AND (txs.season_id = '23') 
  AND (pxt.date_added <= s.end_date OR pxt.date_added is null) 
  AND (pxt.date_removed >= s.start_date OR pxt.date_removed is null) 
GROUP BY `p`.`player_id`

此查询会返回数据,但我的计数已关闭。

+-----------+---------------+-------+-------+---------+
| player_id | jersey_number | games | goals | assists |
+-----------+---------------+-------+-------+---------+
|         2 | 3             |     7 |     1 |       3 | 
|         3 | 19            |     6 |     1 |       0 | 
|         8 | 8             |     7 |     3 |       2 | 
|         9 | 11            |    13 |    10 |       8 | 
|        11 | 96            |     6 |     1 |       3 | 
|        12 | 14            |     6 |     0 |       3 | 
|        13 | 7             |     6 |     0 |       1 | 
|       115 | 39            |     9 |     6 |       2 | 
|       142 | 68            |     6 |     0 |       1 | 
|       143 | 30            |     6 |     0 |       0 | 
|       150 | 41            |    11 |    11 |       5 | 
|       185 | 17            |     6 |     6 |       3 | 
|       225 | 97            |     4 |     1 |       3 | 
+-----------+---------------+-------+-------+---------+

在这个数据集中,应该出现的大多数游戏都是6,但正如你所看到的,我正在获得额外的东西。如果我调整我的查询以删除目标和助攻字段,我的游戏数量就会正确。事实上,如果我只选择一个我计算的行,我总是得到正确的计数,但是一旦我添加了第二或第三个计数,我的数字开始变得偏斜。我做错了什么?

2 个答案:

答案 0 :(得分:3)

也许你需要count(DISTINCT pxg.player_x_game_id) ......?看起来可能有重复的那个巨大的megajoin(我承认我实际上没有花时间完全重现! - )......

答案 1 :(得分:3)

由于您正在进行多个联接,每个联接可能会匹配多个行并转移到下一个联接,因此您需要在distinct中添加count。试试这个:

SELECT `p`.*, 
       `pxt`.`jersey_number`, 
       count(distinct pxg.player_x_game_id) AS `games`, 
       count(distinct goals.scoring_id) AS `goals`, 
       count(distinct assists.scoring_id) AS `assists` 
FROM  `players` AS `p` 
INNER JOIN `players_x_teams` AS `pxt` ON p.player_id = pxt.player_id 
INNER JOIN `teams_x_seasons` AS `txs` ON pxt.team_id = txs.team_id 
INNER JOIN `seasons` AS `s` ON txs.season_id = s.season_id 
INNER JOIN `games` AS `g` ON g.season_id = s.season_id
INNER JOIN `players_x_games` AS `pxg` ON pxg.game_id = g.game_id 
                                     AND pxg.player_id = p.player_id 
LEFT JOIN `scoring` AS `goals` ON goals.game_id = g.game_id 
                              AND goals.scorer_id = p.player_id 
LEFT JOIN `scoring` AS `assists` ON assists.game_id = g.game_id 
                                AND (assists.assist1_id = p.player_id OR assists.assist2_id = p.player_id) 
WHERE (pxt.team_id = 1) 
  AND (txs.season_id = '23') 
  AND (pxt.date_added <= s.end_date OR pxt.date_added is null) 
  AND (pxt.date_removed >= s.start_date OR pxt.date_removed is null) 
GROUP BY `p`.`player_id`