Zeer vergelijkbaar met bestaande antwoorden, maar dit:
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;
geeft dit met de gegevens die je hebt gepost:
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
Als u een nul wilt laten verschijnen in het mynumber
kolom dan kun je dat maken:
select months.month, mv.mycost, coalesce(mv.mynumber, 0) as mynumber
wat geeft:
...
08 DDD 63.32
09 0
10 0
11 0
12 AAA 4337.75
...
Uit de opmerkingen over Jafar's antwoord klinkt het alsof je misschien zo ver bent gekomen in je eentje, maar je wilt nulwaarden voor alle mycost
waarden voor alle maanden. Als dat het geval is, moet u de lijst met mogelijke waarden voor mycost
. opvragen en de buitenste sluit zich daar ook bij aan. Dit neemt alle waarden die al in de MV staan:
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;
en geeft:
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
Maar hopelijk heb je een andere tabel met de mogelijke mycost
waarden (ervan uitgaande dat dit zoiets als een kostenplaats voorstelt, in plaats van een prijs; enigszins moeilijk te zeggen wat wat is) en u kunt dat gebruiken in plaats van de subquery.
Houd er ook rekening mee dat als u een filter wilt toevoegen, b.v. om gegevens te beperken tot een bepaald jaar, moet u dat doen in de left join
clausule, niet als een where
clausule, of je zou de outer join terugzetten naar een inner. Bijvoorbeeld, dit toevoegen
:
where mv.year = 2011
zou betekenen dat je maar twee rijen terug hebt:
MONTH MYCOST MYNUMBER
----- ------ ----------
12 AAA 4337.75
12 BBB 5490.58
Maar als je maakte dan een andere voorwaarde op de outer join je zou nog steeds 48 rijen terugkrijgen, waarvan 46 met nullen en twee met de bovenstaande waarden:
...
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