Très similaire aux réponses existantes, mais ceci :
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;
donne ceci avec les données que vous avez postées :
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
Si vous voulez qu'un zéro apparaisse dans le mynumber
colonne alors vous pouvez faire cela :
select months.month, mv.mycost, coalesce(mv.mynumber, 0) as mynumber
ce qui donne :
...
08 DDD 63.32
09 0
10 0
11 0
12 AAA 4337.75
...
D'après les commentaires sur la réponse de Jafar, il semble que vous en soyez peut-être arrivé là par vous-même, mais vous voulez des valeurs nulles pour tous les mycost
valeurs pour tous les mois. Si tel est le cas, vous devez obtenir la liste des valeurs possibles pour mycost
et jointure externe à cela également. Cela prend toutes les valeurs qui sont déjà dans le 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;
et donne :
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
Mais j'espère que vous avez une autre table qui contient le possible mycost
valeurs (en supposant que cela représente quelque chose comme un centre de coûts, plutôt qu'un prix ; un peu difficile de dire ce qui est quoi) et vous pouvez l'utiliser à la place de la sous-requête.
Notez également que si vous vouliez ajouter un filtre, par ex. pour restreindre les données à une année particulière, vous devez le faire dans la left join
clause, pas comme un where
clause, ou vous renverriez la jointure externe à une jointure interne. Par exemple, ajouter ceci
:
where mv.year = 2011
signifierait que vous n'avez récupéré que deux lignes :
MONTH MYCOST MYNUMBER
----- ------ ----------
12 AAA 4337.75
12 BBB 5490.58
Mais si vous fait qu'une autre condition sur la jointure externe vous obtiendrez toujours 48 lignes, dont 46 avec des zéros et deux avec les valeurs ci-dessus :
...
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