This code works as expected, but I it's long and creepy.
select p.name, p.played, w.won, l.lost from
(select users.name, count(games.name) as played
from users
inner join games on games.player_1_id = users.id
where games.winner_id > 0
group by users.name
union
select users.name, count(games.name) as played
from users
inner join games on games.player_2_id = users.id
where games.winner_id > 0
group by users.name) as p
inner join
(select users.name, count(games.name) as won
from users
inner join games on games.player_1_id = users.id
where games.winner_id = users.id
group by users.name
union
select users.name, count(games.name) as won
from users
inner join games on games.player_2_id = users.id
where games.winner_id = users.id
group by users.name) as w on p.name = w.name
inner join
(select users.name, count(games.name) as lost
from users
inner join games on games.player_1_id = users.id
where games.winner_id != users.id
group by users.name
union
select users.name, count(games.name) as lost
from users
inner join games on games.player_2_id = users.id
where games.winner_id != users.id
group by users.name) as l on l.name = p.name
As you can see, it consists of 3 repetitive parts for retrieving:
- player name and the amount of games they played
- player name and the amount of games they won
- player name and the amount of games they lost
And each of those also consists of 2 parts:
- player name and the amount of games in which they participated as player_1
- player name and the amount of games in which they participated as player_2
How could this be simplified?
The result looks like so:
name | played | won | lost
---------------------------+--------+-----+------
player_a | 5 | 2 | 3
player_b | 3 | 2 | 1
player_c | 2 | 1 | 1
Since this is a quest against "long and creepy", the query can be considerably shorter, yet. Even in pg 9.3 (or actually any version):
More explanation:
In pg 9.4 this can be cleaner with the new Aggregate FILTER clause (like @Joe already mentioned).
This is a case where correlated subqueries may simplify the logic:
This assumes that there are no ties.