Molto simile alle risposte esistenti, ma questo:
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;
dà questo con i dati che hai pubblicato:
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
Se vuoi che uno zero appaia nel mynumber
colonna quindi puoi farlo:
select months.month, mv.mycost, coalesce(mv.mynumber, 0) as mynumber
che dà:
...
08 DDD 63.32
09 0
10 0
11 0
12 AAA 4337.75
...
Dai commenti sulla risposta di Jafar sembra che forse sei arrivato così lontano da solo ma vuoi valori zero per tutti mycost
valori per tutti i mesi. In tal caso, devi ottenere l'elenco dei possibili valori per mycost
e anche esterno si unisce a quello. Questo sta prendendo tutti i valori che sono già nella 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;
e dà:
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
Ma si spera che tu abbia un'altra tabella che contiene il possibile mycost
valori (supponendo che rappresenti qualcosa come un centro di costo, piuttosto che un prezzo; un po' difficile dire cosa sia) e puoi usarlo al posto della sottoquery.
Tieni inoltre presente che se desideri aggiungere un filtro, ad es. per limitare i dati a un anno particolare, dovresti farlo nel left join
clausola, non come un where
clausola o ripristinare il join esterno in uno interno. Ad esempio, aggiungendo questo
:
where mv.year = 2011
significherebbe che hai recuperato solo due righe:
MONTH MYCOST MYNUMBER
----- ------ ----------
12 AAA 4337.75
12 BBB 5490.58
Ma se hai fatto di un'altra condizione sull'outer join avresti comunque 48 righe indietro, di cui 46 con zeri e due con i valori sopra:
...
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