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

Динамично добавяне на записи с нулева стойност за последващи AP за работа на аналитичната функция

Доста опростен подход (и подобен на това, което показва връзката към AskTom) е да извлечете всички двойки година/месец и всички двойки име/r_group и след това да ги свържете кръстосано:

with data as (
  select 1 id, 'A' name, 'fruit' r_group, '2007' year, '04' month, 5 sales from dual union all
  select 2 id, 'Z' name, 'fruit' r_group, '2007' year, '04' month, 99 sales from dual union all
  select 3 id, 'A' name, 'fruit' r_group, '2008' year, '05' month, 10 sales from dual union all
  select 4 id, 'B' name, 'vegetable' r_group, '2008' year, '07' month, 20 sales from dual
)
select a.year, a.month, b.name, b.r_group, nvl(d.sales, 0) as sales
from (select distinct year, month from data) a
cross join (select distinct name, r_group from data) b
left join data d on d.year = a.year and d.month = a.month and d.name = b.name and d.r_group = b.r_group
order by year, month, name, r_group;

YEAR MO N R_GROUP        SALES
---- -- - --------- ----------
2007 04 A fruit              5
2007 04 B vegetable          0
2007 04 Z fruit             99
2008 05 A fruit             10
2008 05 B vegetable          0
2008 05 Z fruit              0
2008 07 A fruit              0
2008 07 B vegetable         20
2008 07 Z fruit              0

Но това произвежда повече редове, отколкото сте искали с вашето първо ниво за агрегиране:

YEAR MO N R_GROUP        SALES    OPENING    CLOSING
---- -- - --------- ---------- ---------- ----------
2007 04 A fruit              5          0          5
2007 04 B vegetable          0          0          0
2007 04 Z fruit             99          0         99
2008 05 A fruit             10          5         15
2008 05 B vegetable          0          0          0
2008 05 Z fruit              0         99         99
2008 07 A fruit              0         15         15
2008 07 B vegetable         20          0         20
2008 07 Z fruit              0         99         99

и когато се агрегира с вашето второ ниво (от другата заявка) ще произведе допълнителни редове за, да речем, 2007/04/vegetable:

YEAR MO R_GROUP        SALES    OPENING    CLOSING
---- -- --------- ---------- ---------- ----------
2007 04 fruit            104          0        104
2007 04 vegetable          0          0          0
2008 05 fruit             10        104        114
2008 05 vegetable          0          0          0
2008 07 fruit              0        114        114
2008 07 vegetable         20          0         20

които бихте могли частично да филтрирате, преди да обобщите, защото всички междинни колони ще бъдат нула:

with data as (
  select 1 id, 'A' name, 'fruit' r_group, '2007' year, '04' month, 5 sales from dual union all
  select 2 id, 'Z' name, 'fruit' r_group, '2007' year, '04' month, 99 sales from dual union all
  select 3 id, 'A' name, 'fruit' r_group, '2008' year, '05' month, 10 sales from dual union all
  select 4 id, 'B' name, 'vegetable' r_group, '2008' year, '07' month, 20 sales from dual
)
select year,
       month,
       r_group,
       sum(sales) sales,
       sum(opening) opening,
       sum(closing) closing
from (
  select t.*,
         (sum(sales) over (partition by name, r_group
                           order by year, month
                           rows between unbounded preceding and current row
                          ) -sales ) as opening,
         sum(sales) over (partition by name, r_group
                          order by year, month
                          rows between unbounded preceding and current row
                         ) as closing
  from (
    select a.year, a.month, b.name, b.r_group, nvl(d.sales, 0) as sales
    from (select distinct year, month from data) a
    cross join (select distinct name, r_group from data) b
    left join data d
    on d.year = a.year and d.month = a.month and d.name = b.name and d.r_group = b.r_group
  ) t
)
where sales != 0 or opening != 0 or closing != 0
group by year, month, r_group
order by year, month;

за да получите:

YEAR MO R_GROUP        SALES    OPENING    CLOSING
---- -- --------- ---------- ---------- ----------
2007 04 fruit            104          0        104
2008 05 fruit             10        104        114
2008 07 fruit              0        114        114
2008 07 vegetable         20          0         20

Можете допълнително да филтрирате този резултат, за да премахнете редове, където обобщената стойност на продажбите все още е нула, но ако правите това, филтърът преди агрегирането вече не е необходимо; но пак е малко разхвърляно. И не е ясно дали вашата най-външна агрегация може да бъде модифицирана, за да направи това.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на оператор Merge за единична таблица

  2. Как да направя текущи суми от втората колона

  3. Има ли някаква причина да използвате първичен ключ и уникален ключ заедно в едно и също поле?

  4. Защо Oracle varchar2 има задължителен размер като дефиниционен параметър?

  5. Отпечатайте текст в прозореца на работния лист на Oracle SQL Developer SQL