Много подобно на съществуващите отговори, но това:
select months.month, mv.mycost, coalesce(mv.mynumber, 0) as mynumber
from (
select to_char(date '1970-01-01'
+ numtoyminterval(level - 1, 'month'), 'mm') as month
from dual
connect by level <= 12) months
left join myoracle_mv mv
on mv.month = months.month
order by months.month, mv.mycost, mv.mynumber;
дава това с публикуваните от вас данни:
MONTH MYCOST MYNUMBER
----- ------ ----------
01 AAA 3777.24
01 BBB 18811
01 CCC 3845.47
02 AAA 49973.12
02 BBB 29872.67
02 CCC 3050.54
03 AAA 4049.91
03 BBB 29068.55
03 CCC 3784.44
03 DDD 107.07
04 AAA 469.485
04 BBB 264957.8
04 CCC 799.73
04 DDD 181.78
05 AAA 5872.22
05 BBB 67673
05 CCC 124884.2
05 DDD 110.09
06 AAA 65837.71
06 BBB 855.02
06 CCC 5157.24
06 DDD 18016.19
07 AAA 566.23
07 BBB 5226.1
07 CCC 19184.78
07 DDD 1772.95
08 AAA 18432.95
08 BBB 2663.24
08 CCC 2280.05
08 DDD 63.32
09 0
10 0
11 0
12 AAA 4337.75
12 BBB 5490.58
35 rows selected
Ако искате да се появи нула в mynumber
след това можете да направите това:
select months.month, mv.mycost, coalesce(mv.mynumber, 0) as mynumber
което дава:
...
08 DDD 63.32
09 0
10 0
11 0
12 AAA 4337.75
...
От коментарите за отговора на Джафар звучи, че може би сте стигнали дотам сами, но искате нулеви стойности за всички mycost
стойности за всички месеци. Ако случаят е такъв, трябва да получите списък с възможни стойности за mycost
и външно присъединяване към това също. Това приема всички стойности, които вече са в MV:
select months.month, costs.mycost, coalesce(mv.mynumber, 0) as mynumber
from (
select to_char(date '1970-01-01'
+ numtoyminterval(level - 1, 'month'), 'mm') as month
from dual
connect by level <= 12) months
cross join (
select distinct mycost
from myoracle_mv) costs
left join myoracle_mv mv
on mv.month = months.month
and mv.mycost = costs.mycost
order by months.month, costs.mycost, mv.mynumber;
и дава:
MONTH MYCOST MYNUMBER
----- ------ ----------
01 AAA 3777.24
01 BBB 18811
01 CCC 3845.47
01 DDD 0
02 AAA 49973.12
02 BBB 29872.67
02 CCC 3050.54
02 DDD 0
03 AAA 4049.91
03 BBB 29068.55
03 CCC 3784.44
03 DDD 107.07
04 AAA 469.485
04 BBB 264957.8
04 CCC 799.73
04 DDD 181.78
05 AAA 5872.22
05 BBB 67673
05 CCC 124884.2
05 DDD 110.09
06 AAA 65837.71
06 BBB 855.02
06 CCC 5157.24
06 DDD 18016.19
07 AAA 566.23
07 BBB 5226.1
07 CCC 19184.78
07 DDD 1772.95
08 AAA 18432.95
08 BBB 2663.24
08 CCC 2280.05
08 DDD 63.32
09 AAA 0
09 BBB 0
09 CCC 0
09 DDD 0
10 AAA 0
10 BBB 0
10 CCC 0
10 DDD 0
11 AAA 0
11 BBB 0
11 CCC 0
11 DDD 0
12 AAA 4337.75
12 BBB 5490.58
12 CCC 0
12 DDD 0
48 rows selected
Но се надяваме, че имате друга таблица, която съдържа възможните mycost
стойности (ако приемем, че това представлява нещо като разходен център, а не цена; малко е трудно да се каже какво е какво) и можете да използвате това вместо подзаявката.
Също така имайте предвид, че ако искате да добавите филтър, напр. за да ограничите данните до определена година, ще трябва да направите това в left join
клауза, а не като where
клауза, или бихте върнали външното съединение към вътрешно. Например добавяне на това
:
where mv.year = 2011
би означавало, че сте върнали само два реда:
MONTH MYCOST MYNUMBER
----- ------ ----------
12 AAA 4337.75
12 BBB 5490.58
Но ако поставите друго условие за външното присъединяване пак ще получите 48 реда обратно, като 46 от тях имат нули, а два имат стойностите по-горе:
...
left join myoracle_mv mv
on mv.month = months.month
and mv.mycost = costs.mycost
and mv.year = 2011
order by months.month, costs.mycost, mv.mynumber;
...
11 CCC 0
11 DDD 0
12 AAA 4337.75
12 BBB 5490.58
12 CCC 0
12 DDD 0
48 rows selected