Reputation: 4350
I'm not sure how to ask this question in a way that Google will understand. I want to left join two tables and have the blank fields filled in. Here's what I'm working with:
tbl1
| user | date | usage |
| us1 | 01/12 | 503 |
| us1 | 02/12 | 245 |
| us1 | 03/12 | 465 |
| us2 | 02/12 | 327 |
| us2 | 03/12 | 204 |
| us3 | 02/12 | 156 |
tbl2
| dates | avg_use |
| 01/12 | 345 |
| 02/12 | 426 |
| 03/12 | 502 |
Desired output
| user | date | usage | pct_of_avg |
| us1 | 01/12 | 503 | 1.45 |
| us1 | 02/12 | 245 | .58 |
| us1 | 03/12 | 465 | .93 |
| us2 | 01/12 | (null) | 0 |
| us2 | 02/12 | 327 | .95 |
| us2 | 03/12 | 204 | .41 |
| us3 | 01/12 | (null) | 0 |
| us3 | 02/12 | 156 | .37 |
| us3 | 03/12 | (null) | 0 |
I understand JOINs pretty well, so I'm aware that a typical JOIN will not be able to do this since the data in tbl1.user won't exist. Is there a way to do this in SQL at all? Bonus points for giving what I'm trying to do a name, because it would help a lot just to know how to Google this :)
Upvotes: 0
Views: 1779
Reputation: 27261
If your Oracle version 10g or higher you can use partition by extension of outer join
to fill in gaps in data. You will need less code. It'll be simpler, faster.
SQL> select t.user1
2 , to_char(t1.dates, 'mm/yy') as date1
3 , t.usage1
4 , round((nvl(t.usage1, 0)/t1.avg_use), 2) as pct_of_avg
5 from tbl1 t
6 partition by(t.user1)
7 right join tbl2 t1
8 on (t.date1 = t1.dates)
9 ;
USER1 DATE1 USAGE1 PCT_OF_AVG
----- ----- ---------- ----------
us1 01/12 503 1.46
us1 02/12 245 0.58
us1 03/12 465 0.93
us2 01/12 0
us2 02/12 327 0.77
us2 03/12 204 0.41
us3 01/12 0
us3 02/12 156 0.37
us3 03/12 0
9 rows selected
Upvotes: 2
Reputation: 70668
This should do it:
SELECT U.user, T2.dates date, T1.usage, T1.usage/T2.avg_use pct_of_avg
FROM (SELECT DISTINCT user FROM tbl1) U
CROSS JOIN tbl2 T2
LEFT JOIN tbl1 T1
ON T2.date = T1.date AND U.user = T1.user
Upvotes: 3