Reputation: 631
I'm pretty new to sql and I've been trying something with very little luck. Here's my situation. I have tableA that has multiple links to another tableB:
select * from tableA where id = 1;
+--+---------+---------+---------+
|ID|TABLEB1ID|TABLEB2ID|TABLEB3ID|
+--+---------+---------+---------+
|1 |1 |2 |3 |
+--+---------+---------+---------+
select * from tableB;
+--+----+
|ID|NAME|
+--+----+
|1 |A |
+--+----+
|2 |B |
+--+----+
|3 |C |
+--+----+
Now, I want to get values from each of the rows corresponding to those 3 ids. Right now I'm doing something like this:
select tableA.*, tableB1.name name1, tableB2.name name2, tableB3.name name3
from tableA, tableB tableB1, tableB tableB2, tableB tableB3
where tableA.id = 1 and
tableA.tableB1id = tableB1.id and
tableA.tableB2id = tableB2.id and
tableA.tableB3id = tableB3.id;
+--+---------+---------+---------+-----+-----+-----+
|ID|TABLEB1ID|TABLEB2ID|TABLEB3ID|NAME1|NAME2|NAME3|
+--+---------+---------+---------+-----+-----+-----+
|1 |1 |2 |3 |A |B |C |
+--+---------+---------+---------+-----+-----+-----+
Now this works great except that when one of these ids is null, I get no results:
select * from tableA where id = 2;
+--+---------+---------+---------+
|ID|TABLEB1ID|TABLEB2ID|TABLEB3ID|
+--+---------+---------+---------+
|2 |1 |2 | |
+--+---------+---------+---------+
select tableA.*, tableB1.name name1, tableB2.name name2, tableB3.name name3
from tableA, tableB tableB1, tableB tableB2, tableB tableB3
where tableA.id = 2 and
tableA.tableB1id = tableB1.id and
tableA.tableB2id = tableB2.id and
tableA.tableB3id = tableB3.id;
+--+---------+---------+---------+-----+-----+-----+
|ID|TABLEB1ID|TABLEB2ID|TABLEB3ID|NAME1|NAME2|NAME3|
+--+---------+---------+---------+-----+-----+-----+
+--+---------+---------+---------+-----+-----+-----+
I'm not too familiar with all the functionality that SQL has, and I would appreciate any help in getting the output like the following:
+--+---------+---------+---------+-----+-----+-----+
|ID|TABLEB1ID|TABLEB2ID|TABLEB3ID|NAME1|NAME2|NAME3|
+--+---------+---------+---------+-----+-----+-----+
|2 |1 |2 | |A |B | |
+--+---------+---------+---------+-----+-----+-----+
OR
+--+---------+---------+-----+-----+
|ID|TABLEB1ID|TABLEB2ID|NAME1|NAME2|
+--+---------+---------+-----+-----+
|2 |1 |2 |A |B |
+--+---------+---------+-----+-----+
I know there has to be a function that can help me with this, I'm just having trouble finding that, and writing the query. Any help would be great. Thanks.
Upvotes: 2
Views: 108
Reputation: 23588
An alternative to the left outer join would be to use subqueries in the select list:
select t1.*,
(select t2.name from tableb t2 where t1.tableb1id = t2.id) name1,
(select t3.name from tableb t3 where t1.tableb2id = t3.id) name2,
(select t4.name from tableb t4 where t1.tableb3id = t4.id) name3
from tableA t1;
ID TABLEB1ID TABLEB2ID TABLEB3ID NAME1 NAME2 NAME3
---------- ---------- ---------- ---------- ----- ----- -----
1 1 2 3 A B C
2 1 2 A B
This has the benefit of enabling subquery caching, which may or may not provide performance benefits depending on whether your data has many repeat values or not. You should test both queries against your data to see which one performs best for you.
Upvotes: 1
Reputation: 16917
You need to use a LEFT OUTER JOIN
for this approach. The type of JOIN
you're doing right now is the equivalent of an INNER JOIN
, which won't return unless both sides of all joins are satisfied, which is why you aren't getting any results.
With an OUTER JOIN
, if the data does not exist for any of the TableB
variants, you will simply get back NULL
.
Try the following instead:
Select A.*,
B1.Name Name1,
B2.Name Name2,
B3.Name Name3
From TableA A
Left Join TableB B1 On A.TableB1ID = B1.Id
Left Join TableB B2 On A.TableB2ID = B2.Id
Left Join TableB B3 On A.TableB3ID = B3.Id
Where A.Id = 2;
Upvotes: 3