sql >> Database >  >> RDS >> Oracle

Dynamisch toevoegen van records met nulwaarde voor volgende AP's om de analytische functie te laten werken

Een vrij simplistische benadering (en vergelijkbaar met wat die AskTom-link laat zien) is om alle jaar/maand-paren en alle naam/r_groep-paren te extraheren en deze vervolgens te kruisen:

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

Maar dat levert meer rijen op dan je wilde met je fo-aggregatie op het eerste niveau:

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

en wanneer geaggregeerd met uw tweede niveau (van de andere zoekopdracht), zou dit extra rijen opleveren voor, laten we zeggen, 2007/04/groente:

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

die je er gedeeltelijk uit zou kunnen filteren voordat je ze aggregeert, omdat alle tussenliggende kolommen nul zouden zijn:

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;

te krijgen:

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

U kunt dat resultaat verder filteren om rijen te verwijderen waarvan de totale verkoopwaarde nog steeds nul is, maar als u dat doet, filtert u voor aggregatie is niet meer nodig; maar het blijft een beetje rommelig. En het is niet duidelijk of je buitenste aggregatie daarvoor kan worden aangepast.



  1. Een bestaande database koppelen met MySQL

  2. Hoe kan ik voorkomen dat het vervangende teken verandert in een html-entiteit in PHP?

  3. mysql-connector python 'IN'-operator opgeslagen als lijst

  4. hoe globale variabele declareren in SQL Server ..?