Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle:Daten für alle Monate abrufen, 0, wenn keine Daten vorhanden sind

Sehr ähnlich zu bestehenden Antworten, aber dies:

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;

gibt dies mit den von Ihnen geposteten Daten aus:

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

Wenn Sie möchten, dass in mynumber eine Null erscheint Spalte dann kannst du das machen:

select months.month, mv.mycost, coalesce(mv.mynumber, 0) as mynumber

was ergibt:

...
08    DDD         63.32 
09                    0 
10                    0 
11                    0 
12    AAA       4337.75 
...

Aus den Kommentaren zu Jafars Antwort klingt es so, als wären Sie vielleicht alleine so weit gekommen, aber Sie möchten Nullwerte für alle mycost Werte für alle Monate. Wenn dies der Fall ist, müssen Sie die Liste der möglichen Werte für mycost abrufen und äußerer Join dazu. Dies nimmt alle Werte, die bereits im MV sind:

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;

und ergibt:

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 

Aber hoffentlich haben Sie eine andere Tabelle, die die möglichen mycost enthält Werte (vorausgesetzt, es handelt sich eher um eine Kostenstelle als um einen Preis; etwas schwer zu sagen, was was ist), und Sie können diese anstelle der Unterabfrage verwenden.

SQL-Geige .

Beachten Sie auch, dass Sie, wenn Sie einen Filter hinzufügen möchten, z. Um die Daten auf ein bestimmtes Jahr zu beschränken, müssen Sie dies im left join tun -Klausel, nicht als where -Klausel, oder Sie würden den äußeren Join in einen inneren zurücksetzen. Beispiel:Hinzufügen :

where mv.year = 2011

würde bedeuten, dass Sie nur zwei Zeilen zurückbekommen:

MONTH MYCOST   MYNUMBER
----- ------ ----------
12    AAA       4337.75 
12    BBB       5490.58 

Aber wenn Sie als eine andere Bedingung für den äußeren Join gemacht haben Sie würden immer noch 48 Zeilen zurückbekommen, von denen 46 Nullen und zwei die obigen Werte haben:

...
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