Reputation: 586
Assuming following simplified situation:
On a birthday party two games are provided (Darts and Bowling). The scores of each guest for each game are stored in separate tables:
Darts: Bowling:
Name | Dart-Score Name | Bowling-Score
------------------ --------------------
Alice | 120 Bob | 25
Tim | 90 Alice | 8
Now I want to join the tables like this (ordered by Name):
Name | Dart-Score | Bowling-Score
---------------------------------
Alice | 120 | 8
Bob | NULL | 25
Tim | 90 | NULL
My approach was the following:
select *
from Darts d full outer join Bowling b on (d.Name=b.Name)
order by Name;
This obviously throws an error, since Name
is ambiguous in the join table:
Darts.Name | Dart-Score | Bowling.Name | Bowling-Score
-------------------------------------------------------
Alice | 120 | Alice | 8
Tim | 90 | NULL | NULL
NULL | NULL | Bob | 25
Also, I cannot order along, e.g., Darts.Name, since some values are NULL
. So, how can I order the result along the join attribute of a full outer join
? Or is an outer join
the wrong approach in this scenario?
My Solution:
Thanks to @jarlh and @Radu Gheorghiu I used the follwoing query:
select coalesce(d.Name,b.Name) Names, Dart-Score, Bowling-Score
from Darts d full outer join Bowling b on (d.Name=b.Name)
order by Names;
Upvotes: 1
Views: 54
Reputation: 5588
Execute query as per below and Fiddle link:
-- First union all values and group by name in query:
create table Darts(id integer, Name varchar(25), DartScore integer);
create table Bowling(id integer, Name varchar(25), BowlingScore integer);
insert into Darts values(1, 'Alice',120);
insert into Darts values(1, 'Tim',90);
insert into Bowling values(1, 'Bob',25);
insert into Bowling values(1, 'Alice',8);
select name, DartScore, NULL as BowlingScore from Darts
union all
select name, NULL as DartScore, BowlingScore from Bowling;
select name, SUM(DartScore) as DartScore from Darts group by name;
select name, SUM(DartScore) as DartScore, SUM(BowlingScore) as BowlingScore
from (
select name, DartScore, NULL as BowlingScore from Darts
union all
select name, NULL as DartScore, BowlingScore from Bowling
)
group by name;
Upvotes: 0
Reputation: 1787
Alternatively, you can internally create an exhaustive list of names and left join
with each of those two tables to create a common Name
column in the output.
select a.Name, d.Dart-Score, b.Bowling-Score
from
(select name from Darts
UNION
select name from Bowling) a
LEFT JOIN
Darts d on a.Name = d.Name
LEFT JOIN
Bowling b on a.Name = b.Name
ORDER BY a.Name;
ORDER BY
can be applied to the UNIONED list.
Upvotes: 1
Reputation: 20509
NVL(d.Name, b.Name)
or COALESCE(d.Name, b.Name)
Since it's a full join, one of the columns will have a name. And by using NVL()
you will always get a non-NULL result.
OUTER JOIN
is the right approach in this scenario.Upvotes: 1