sql >> Databáze >  >> RDS >> Oracle

Oracle:Získejte data za všechny měsíce, 0, pokud žádná data

Velmi podobné existujícím odpovědím, ale toto:

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ává toto s daty, které jste odeslali:

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

Pokud chcete, aby se v mynumber objevila nula sloupec, pak to můžete udělat:

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

což dává:

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

Z komentářů k Jafarově odpovědi to zní, jako byste se možná dostali tak daleko sami, ale chcete nulové hodnoty pro všechny mycost hodnoty za všechny měsíce. Pokud je tomu tak, musíte získat seznam možných hodnot pro mycost a vnější se k tomu také připojují. Toto přebírá všechny hodnoty, které jsou již v 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;

a dává:

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 

Ale doufejme, že máte jinou tabulku, která obsahuje possble mycost hodnoty (za předpokladu, že to představuje něco jako nákladové středisko, spíše než cenu; trochu těžko říct, co je co) a můžete to použít místo dílčího dotazu.

SQL Fiddle .

Všimněte si také, že pokud byste chtěli přidat filtr, např. Chcete-li omezit data na konkrétní rok, musíte to udělat v left join klauzule, nikoli jako where klauzule, nebo byste změnili vnější spojení na vnitřní. Například přidání tohoto :

where mv.year = 2011

znamenalo by to, že jste dostali zpět pouze dva řádky:

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

Ale pokud jste udělali další podmínku na vnějším spojení stále dostanete 48 řádků zpět, přičemž 46 z nich má nuly a dva mají hodnoty výše:

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


  1. Jak vybrat název domény z e-mailové adresy

  2. Co znamená dvojtečka před literálem v příkazu SQL?

  3. Změňte uživatelsky definovaný typ v SQL Server

  4. Získejte data ze dvou tabulek a vytvořte kalendář událostí