Oracle
 sql >> база данни >  >> RDS >> Oracle

Oracle:Вземете данни за всички месеци, 0, ако няма данни

Много подобно на съществуващите отговори, но това:

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;

дава това с публикуваните от вас данни:

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

Ако искате да се появи нула в mynumber след това можете да направите това:

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

което дава:

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

От коментарите за отговора на Джафар звучи, че може би сте стигнали дотам сами, но искате нулеви стойности за всички mycost стойности за всички месеци. Ако случаят е такъв, трябва да получите списък с възможни стойности за mycost и външно присъединяване към това също. Това приема всички стойности, които вече са в 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;

и дава:

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 

Но се надяваме, че имате друга таблица, която съдържа възможните mycost стойности (ако приемем, че това представлява нещо като разходен център, а не цена; малко е трудно да се каже какво е какво) и можете да използвате това вместо подзаявката.

SQL Fiddle .

Също така имайте предвид, че ако искате да добавите филтър, напр. за да ограничите данните до определена година, ще трябва да направите това в left join клауза, а не като where клауза, или бихте върнали външното съединение към вътрешно. Например добавяне на това :

where mv.year = 2011

би означавало, че сте върнали само два реда:

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

Но ако поставите друго условие за външното присъединяване пак ще получите 48 реда обратно, като 46 от тях имат нули, а два имат стойностите по-горе:

...
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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. С изключение на неподдържани таблици, които да бъдат заснети от потоци на Oracle

  2. Как правилно да експортирате резултатите от оператора select в Csv файл, като използвате spool в oracle sql developer

  3. Как мога да създам таблица с оракул, но с малки знаци?

  4. Как да изпълните PL SQL блок в Oracle

  5. Прочетете и импортирайте XLSX (Excel) файл в Oracle