如何获得缺失月份的价值

时间:2018-03-02 06:33:58

标签: sql oracle

我有一个样本表:

Month     Id1 Id2 Id3  value1  value2 
Dec-17     1   1   1     10     10
Jan-18     1   1   1     null   null
Feb-18     1   1   1     20     10
Mar-18     1   1   1     20     10
Apr-18     1   1   1     10     30
Jan-18     2   2   2     10     20
Mar-18     2   2   2     10     10

我的表的复合键是月+ Id1 + Id2 + Id3。 根据季度的月份,我想应用一些逻辑。 例如,对于本季度的每个月,产出应为前几个月的总和以及当前和未来月份的总和

我想使用滞后和导联功能,我使用分区(Id1,Id2,Id3),所以我不想要null我想要Id1,Id2,Id3中的0。我认为使用左外join以获取所有月份,但会在Id1,Id2,Id3中填充null或0。

我想根据月份使用滞后和潜在客户,我需要考虑逻辑中的下一个和前几个月 有人可以帮忙吗

2 个答案:

答案 0 :(得分:4)

您似乎想要显示该月所在季度的总值。您可以使用分析sum()而不是lag()

sum(value) over (partition by id1, id2, id3, trunc(month, 'Q'))

演示,通过CTE获取样本数据,还包括有趣的季度至今的价值::

with your_table(Month, Id1, Id2, Id3, value) as (
            select date '2017-12-01', 1, 1, 1, 10 from dual
  union all select date '2018-02-01', 1, 1, 1, 10 from dual
  union all select date '2018-04-01', 1, 1, 1, 10 from dual
  union all select date '2018-05-01', 1, 1, 1, 10 from dual
  union all select date '2018-09-01', 1, 1, 1, 20 from dual
)
select to_char(month, 'Mon-RR', 'nls_date_language=english') as month,
  id1, id2, id3, value,
  sum(value) over (partition by id1, id2, id3, trunc(month, 'Q')) as qtr,
  sum(value) over (partition by id1, id2, id3, trunc(month, 'Q')
    order by month) as qtd
from your_table;

MONTH         ID1        ID2        ID3      VALUE        QTR        QTD
------ ---------- ---------- ---------- ---------- ---------- ----------
Dec-17          1          1          1         10         10         10
Feb-18          1          1          1         10         10         10
Apr-18          1          1          1         10         20         10
May-18          1          1          1         10         20         20
Sep-18          1          1          1         20         20         20

缺少月份不存在因此不影响总和。 (如果有几个月但是将值设置为null而不是零,那么你会遇到问题;但是那时你可以合并它们。)

根据您的最新更新,您有两个值;您希望在本季度的任何前几个月使用value1,并在本季度和本季度的任何未来月份使用value2

你可以得到那些有合适窗口条款的人;再次使用CTE为您提供新的样本数据:

with your_table(month, id1, id2, id3, value1, value2) as (
            select date '2017-12-01', 1, 1, 1, 10, 10 from dual
  union all select date '2018-01-01', 1, 1, 1, null, null from dual
  union all select date '2018-02-01', 1, 1, 1, 10, 10 from dual
  union all select date '2018-03-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-04-01', 1, 1, 1, 10, 30 from dual
  union all select date '2018-05-01', 1, 1, 1, 10, 10 from dual
  union all select date '2018-09-01', 1, 1, 1, 20, 10 from dual
)
select to_char(month, 'Mon-RR', 'nls_date_language=english') as month,
  id1, id2, id3, value1, value2,
  coalesce(sum(coalesce(value1, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between unbounded preceding and 1 preceding
  ), 0) as qbd_value1,
  coalesce(sum(coalesce(value2, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between current row and unbounded following
  ), 0) as qfd_value2,
  coalesce(sum(coalesce(value1, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between unbounded preceding and 1 preceding
  ), 0)
  +
  coalesce(sum(coalesce(value2, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between current row and unbounded following
  ), 0) as qtr_value
from your_table;

得到:

MONTH  ID1 ID2 ID3 VALUE1 VALUE2 QBD_VALUE1 QFD_VALUE2  QTR_VALUE
------ --- --- --- ------ ------ ---------- ---------- ----------
Dec-17   1   1   1     10     10          0         10         10
Jan-18   1   1   1                        0         20         20
Feb-18   1   1   1     10     10          0         20         20
Mar-18   1   1   1     20     10         10         10         20
Apr-18   1   1   1     10     30          0         40         40
May-18   1   1   1     10     10         10         10         20
Sep-18   1   1   1     20     10          0         10         10

您无需选择value1qbd_value1)之前的季度总和或value2之间的季度总和(qfd_value2 )价值分开,我只是包括它们,所以你可以看到/检查它们;相关部分是将它们加在一起生成qtr_value

所以:

  • 对于Jan,它给出了Jan value2(null-> 0)+ Feb value2(10)+ Mar value2(10)=> 20。

  • 对于2月,它给出了Jan value1(null-> 0)+ Feb value2(10)+ Mar value2(10)=> 20。

  • 对于Mar,它给出了Jan value1(null-> 0)+ Feb value1(10)+ Mar value1(10)=> 20。

不是最有帮助的样本数据......

  • for Apr它给你4月value2(30)+ May value2(10)=> 40.(没有6月的数据)
  • for May它给你4月value1(10)+ May value2(10)=> 20。

使用您的最新样本数据:

with your_table(month, id1, id2, id3, value1, value2) as (
            select date '2017-12-01', 1, 1, 1, 10, 10 from dual
  union all select date '2018-01-01', 1, 1, 1, null, null from dual
  union all select date '2018-02-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-03-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-04-01', 1, 1, 1, 10, 30 from dual
  union all select date '2018-01-01', 2, 2, 2, 10, 20 from dual
  union all select date '2018-03-01', 2, 2, 2, 10, 10 from dual
)
...

相同的查询得到:

MONTH  ID1 ID2 ID3 VALUE1 VALUE2 QBD_VALUE1 QFD_VALUE2  QTR_VALUE
------ --- --- --- ------ ------ ---------- ---------- ----------
Dec-17   1   1   1     10     10          0         10         10
Jan-18   1   1   1                        0         20         20
Feb-18   1   1   1     20     10          0         20         20
Mar-18   1   1   1     20     10         20         10         30
Apr-18   1   1   1     10     30          0         30         30
Jan-18   2   2   2     10     20          0         30         30
Mar-18   2   2   2     10     10         10         10         20

这似乎符合您的期望。

离开原来的问题,但看着不寻常的区域,你可以通过添加分析最小值和最大值来看到正在使用的月份(尽管如果还有缺失的月数,这些会让人感到困惑,所以我重新添加了May null值使它更清晰一点):

with your_table(month, id1, id2, id3, value1, value2) as (
            select date '2017-12-01', 1, 1, 1, 10, 10 from dual
  union all select date '2018-01-01', 1, 1, 1, null, null from dual
  union all select date '2018-02-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-03-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-04-01', 1, 1, 1, 10, 30 from dual
  union all select date '2018-05-01', 1, 1, 1, null, null from dual
  union all select date '2018-01-01', 2, 2, 2, 10, 20 from dual
  union all select date '2018-03-01', 2, 2, 2, 10, 10 from dual
)
select to_char(month, 'Mon-RR', 'nls_date_language=english') as month,
  id1, id2, id3, value1, value2,
  coalesce(sum(coalesce(value1, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between unbounded preceding and 1 preceding
  ), 0) as qbd_value1,
  coalesce(sum(coalesce(value2, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between current row and unbounded following
  ), 0) as qfd_value2,
  coalesce(sum(coalesce(value1, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between unbounded preceding and 1 preceding
  ), 0)
  +
  coalesce(sum(coalesce(value2, 0)) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between current row and unbounded following
  ), 0) as qtr_value,
  to_char(min(month) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between unbounded preceding and current row
  ), 'Mon-RR', 'nls_date_language=english') as qtr_start,
  to_char(max(month) over (
    partition by id1, id2, id3, trunc(month, 'Q')
    order by month
    rows between current row and unbounded following
  ), 'Mon-RR', 'nls_date_language=english') as qtr_end
from your_table;

MONTH  ID1 ID2 ID3 VALUE1 VALUE2 QBD_VALUE1 QFD_VALUE2  QTR_VALUE QTR_START       QTR_END        
------ --- --- --- ------ ------ ---------- ---------- ---------- --------------- ---------------
Dec-17   1   1   1     10     10          0         10         10 Dec-17          Dec-17         
Jan-18   1   1   1                        0         20         20 Jan-18          Mar-18         
Feb-18   1   1   1     20     10          0         20         20 Jan-18          Mar-18         
Mar-18   1   1   1     20     10         20         10         30 Jan-18          Mar-18         
Apr-18   1   1   1     10     30          0         30         30 Apr-18          May-18         
May-18   1   1   1                       10          0         10 Apr-18          May-18         
Jan-18   2   2   2     10     20          0         30         30 Jan-18          Mar-18         
Mar-18   2   2   2     10     10         10         10         20 Jan-18          Mar-18         

要获得调整范围,您可以在add_months()调用中使用trunc(),如评论中所述,在所有分析子句中:

with your_table(month, id1, id2, id3, value1, value2) as (
            select date '2017-12-01', 1, 1, 1, 10, 10 from dual
  union all select date '2018-01-01', 1, 1, 1, null, null from dual
  union all select date '2018-02-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-03-01', 1, 1, 1, 20, 10 from dual
  union all select date '2018-04-01', 1, 1, 1, 10, 30 from dual
  union all select date '2018-05-01', 1, 1, 1, null, null from dual
  union all select date '2018-01-01', 2, 2, 2, 10, 20 from dual
  union all select date '2018-03-01', 2, 2, 2, 10, 10 from dual
)
select to_char(month, 'Mon-RR', 'nls_date_language=english') as month,
  id1, id2, id3, value1, value2,
  coalesce(sum(coalesce(value1, 0)) over (
    partition by id1, id2, id3, trunc(add_months(month, 1), 'Q')
    order by month
    rows between unbounded preceding and 1 preceding
  ), 0) as qbd_value1,
  coalesce(sum(coalesce(value2, 0)) over (
    partition by id1, id2, id3, trunc(add_months(month, 1), 'Q')
    order by month
    rows between current row and unbounded following
  ), 0) as qfd_value2,
  coalesce(sum(coalesce(value1, 0)) over (
    partition by id1, id2, id3, trunc(add_months(month, 1), 'Q')
    order by month
    rows between unbounded preceding and 1 preceding
  ), 0)
  +
  coalesce(sum(coalesce(value2, 0)) over (
    partition by id1, id2, id3, trunc(add_months(month, 1), 'Q')
    order by month
    rows between current row and unbounded following
  ), 0) as qtr_value,
  to_char(min(month) over (
    partition by id1, id2, id3, trunc(add_months(month, 1), 'Q')
    order by month
    rows between unbounded preceding and current row
  ), 'Mon-RR', 'nls_date_language=english') as qtr_start,
  to_char(max(month) over (
    partition by id1, id2, id3, trunc(add_months(month, 1), 'Q')
    order by month
    rows between current row and unbounded following
  ), 'Mon-RR', 'nls_date_language=english') as qtr_end
from your_table;

MONTH  ID1 ID2 ID3 VALUE1 VALUE2 QBD_VALUE1 QFD_VALUE2  QTR_VALUE QTR_START       QTR_END        
------ --- --- --- ------ ------ ---------- ---------- ---------- --------------- ---------------
Dec-17   1   1   1     10     10          0         20         20 Dec-17          Feb-18         
Jan-18   1   1   1                       10         10         20 Dec-17          Feb-18         
Feb-18   1   1   1     20     10         10         10         20 Dec-17          Feb-18         
Mar-18   1   1   1     20     10          0         40         40 Mar-18          May-18         
Apr-18   1   1   1     10     30         20         30         50 Mar-18          May-18         
May-18   1   1   1                       30          0         30 Mar-18          May-18         
Jan-18   2   2   2     10     20          0         20         20 Jan-18          Jan-18         
Mar-18   2   2   2     10     10          0         10         10 Mar-18          Mar-18         

答案 1 :(得分:0)

select 
a.d month,nvl(id1,0) id1,nvl(id2,0) id2,nvl(id3,0) id3,nvl(value,0)value
from 
    ( SELECT TO_CHAR(ADD_MONTHS(DATE '2018-01-01',(level-1)),'Mon-YY') d
FROM  DUAL
CONNECT BY level < 13) a left join mytable
     on a.d=mytable.month

如果有任何疑问 - http://sqlfiddle.com/#!4/7b8c7/14