Reputation: 258
I have the following tables:
Players
- id
- name
Games
- id
- game_type_id
- season_id
Goals
- player_id
- game_id
Assists
- player_id
- game_id
I've been struggling trying to build a query/view that will give me the players' goal and assist counts for each season and game type. It's important to each player is listed for each season and game type, whether they have goals/assists or not.
The query will be used to create a view. Can it be done in one query?
UPDATE: Here's an SQL Fiddle with some production sample data.
Upvotes: 3
Views: 190
Reputation: 3551
UPDATED
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
This isn't very short version, but it should be right now.
Upvotes: 3
Reputation: 247650
try this:
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
Upvotes: 1
Reputation: 3881
Awesome, I didn't think of the cross join, I came up with:
select players.id, games.game_type_id, games.season_id, g.c, a.c from players
left join (select count(id) as c, player_id, game_id from goals group by player_id, game_id) as g on g.player_id = players.id
left join (select count(id) as c, player_id, game_id from assists group by player_id, game_id) as a on a.player_id = players.id
right join games on games.id = g.game_id and games.id = a.game_id group by players.id, games.game_type_id, games.season_id;
Upvotes: 0
Reputation: 86706
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
But it may improve in performance if you had a Seasons
table and a GameType
table.
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
Upvotes: 3