Reputation: 1268
I just started learning SQL the other day and hit a stumbling block. I've got some code that looks like this:
SELECT player, SUM(wins) from (
SELECT win_counts.player, win_counts.wins
from win_counts
UNION
SELECT lose_counts.player, lose_counts.loses
from lose_counts
group by win_counts.player
) as temp_alias
Here is the error I get:
ERROR: missing FROM-clause entry for table "win_counts" LINE 7: group by win_counts.player
This win_counts table contains a list of player ids and the number of matches they have one. The lose_counts tables contains a list of player ids and the number of matches they have lost. Ultimately I want a table of player ids and the total number of matches each player has played.
Thank you for the help. Sorry I don't have more information... my understanding of sql is pretty rudimentary.
Upvotes: 0
Views: 228
Reputation: 17935
You already have a good answer and comments from others. For your edification:
In some scenarios it might be more efficient to aggregate before the union.
select player, sum(wins) from (
select player, count(*) as wins
from win_counts
group by player
UNION ALL /* without ALL you'll eliminate duplicate rows */
select player, count(*) as losses
from lose_counts
group by player
) as t
group by player
This should also give equivalent results if each player has both wins and losses:
select wins.player, wins + losses as total_matches
from
(
select player, count(*) as wins
from win_counts
group by player
) as wins
inner join
(
select player, count(*) as losses
from lose_counts
group by player
) as losses
on losses.player = wins.player
The fix for missing wins/losses is a full outer join:
select
coalesce(wins.player, losses.player) as player,
coalesce(wins. 0) + coalesce(losses, 0) as total_matches
from
(
select player, count(*) as wins
from win_counts
group by player
) as wins
full outer join
(
select player, count(*) as losses
from lose_counts
group by player
) as losses
on losses.player = wins.player
These complicated queries should give you a taste of why it's a bad idea to use separate tables for data that belongs together. In this case you should probably prefer a single table that records all matches as wins, losses (or ties).
Upvotes: 1
Reputation: 35343
Group by appears to be in the wrong place.
SELECT player, SUM(wins) as SumWinsLoses
FROM(
SELECT win_counts.player, win_counts.wins
FROM win_counts
UNION ALL -- as Gordon points out 'ALL' is likely needed, otherwise your sum will be
-- off as the UNION alone will distinct the values before the sum
-- and if you have a player with the same wins and losses (2),
-- the sum will return only 2 instead of (4).
SELECT lose_counts.player, lose_counts.loses
FROM lose_counts) as temp_alias
GROUP BY player
Just so we are clear though the SUm(Wins) will sum wins and losses as "wins" the first name in a union for a field is the name used. So a players wins and losses are going to be aggregated.
Here's a working SQL FIddle Notice without the union all... the player #2 has an improper count.
Upvotes: 5