依靠多个连接表

时间:2012-09-14 16:20:57

标签: mysql sql database

我有以下表格:

Players
- id
- name

Games
- id
- game_type_id
- season_id


Goals
- player_id
- game_id

Assists
- player_id
- game_id

我一直在努力尝试建立一个查询/视图,它将为我提供球员的目标并帮助计算每个赛季和比赛类型。每个球员的每个赛季和比赛类型都很重要,无论他们是否有进球/助攻。

该查询将用于创建视图。可以在一个查询中完成吗?

更新:这是一个带有一些生产样本数据的SQL Fiddle

4 个答案:

答案 0 :(得分:3)

SELECT
  players.id,
  players.name,
  games.season_id,
  games.game_type_id,
  SUM(COALESCE(assists.rows, 0))             AS assists,
  SUM(COALESCE(goals.rows,   0))             AS goals
FROM
  players
CROSS JOIN
  games
LEFT JOIN
  (SELECT game_id, player_id, COUNT(*) AS rows FROM assists GROUP BY game_id, player_id) AS assists
    ON assists.game_id = games.game_id
LEFT JOIN
  (SELECT game_id, player_id, COUNT(*) AS rows FROM goals   GROUP BY game_id, player_id) AS assists
    ON goals.game_id   = games.game_id
GROUP BY
  players.id,
  players.name,
  games.season_id,
  games.game_type_id

但如果你有一个Seasons表和一个GameType表,它可能会提高性能。

SELECT
  players.id,
  players.name,
  seasons.id,
  game_types.id,
  SUM(COALESCE(assists.rows, 0))             AS assists,
  SUM(COALESCE(goals.rows,   0))             AS goals
FROM
  players
CROSS JOIN
  seasons
CROSS JOIN
  game_types
LEFT JOIN
  games
    ON  games.season_id = seasons.id
    AND games.game_type = game_types.id
LEFT JOIN
  (SELECT game_id, player_id, COUNT(*) AS rows FROM assists GROUP BY game_id, player_id) AS assists
    ON assists.game_id = games.game_id
LEFT JOIN
  (SELECT game_id, player_id, COUNT(*) AS rows FROM goals   GROUP BY game_id, player_id) AS assists
    ON goals.game_id   = games.game_id
GROUP BY
  players.id,
  players.name,
  seasons.id,
  game_types.id

答案 1 :(得分:3)

<强>已更新

SELECT
    players.id,
    players.name,
    games.season_id,
    games.game_type_id,
    sum(CASE WHEN g.goals IS NULL THEN 0 ELSE g.goals END) AS goals,
    sum(CASE WHEN a.assists IS NULL THEN 0 ELSE a.assists END) AS assists
FROM players
CROSS JOIN games
LEFT JOIN (
  SELECT
    game_id, player_id,
    count(*) AS goals
  FROM goals
  GROUP BY
    game_id, player_id
) g ON
    g.player_id = players.id
    AND g.game_id = games.id
LEFT JOIN (
  SELECT
    game_id, player_id,
    count(*) AS assists
  FROM assists
  GROUP BY
    game_id, player_id
) a ON
    a.player_id = players.id
    AND a.game_id = games.id
GROUP BY
    players.id,
    players.name,
    games.season_id,
    games.game_type_id

这不是很短的版本,但现在应该是。

答案 2 :(得分:1)

试试这个:

select p.id,
  p.name,
  gm.season_id,
  gm.game_type_id,
  sum(gl.goalcount),
  sum(a.AssistCount)
from players p
left join
(
  select game_id, player_id, count(*) GoalCount
  from goals
  group by game_id, player_id
) gl
  on p.id = gl.player_id
left join
(
  select game_id, player_id, count(*) AssistCount
  from assists
  group by game_id, player_id
) a
  on p.id = a.player_id
left join games gm
  on gl.game_id = gm.id
  and a.game_id = gm.id
where season_id is not null
group by p.id,
  p.name,
  gm.season_id,
  gm.game_type_id

请参阅SQL Fiddle with Demo

答案 3 :(得分:0)

太棒了,我没想到交叉加入,我想出了:

选择    players.id,games.game_type_id,games.season_id,g.c,a.c 来自球员

左连接(选择count(id)为c,player_id,来自目标组的game_id,由player_id,game_id)为g on g.player_id = players.id

左边连接(选择count(id)为c,player_id,game_id来自辅助组by player_id,game_id)作为on a.player_id = players.id

在games.id = g.game_id和games.id = a.game_id上​​加入游戏 group by players.id,games.game_type_id,games.season_id;