通过查询将Oracle Over Partition与所有可用日期进行外部联接

时间:2019-02-19 10:50:30

标签: sql oracle sql-order-by partition-by

我正在开发一个Oracle SQL查询,该查询将找到一个按两个字段维分组的数字字段的累积和。

我正在使用Oracle销售历史记录架构中的SALES表作为参考。

实际查询如下:

Select DISTINCT CHANNEL_ID, PROD_ID, TIME_ID, SUM (AMOUNT_SOLD) OVER (PARTITION BY CHANNEL_ID, PROD_ID ORDER BY TIME_ID) AS "Cumulative Sum" 
From SH.SALES
Order By CHANNEL_ID ASC, PROD_ID ASC, TIME_ID ASC;

查询结果:

CHANNEL_ID    PROD_ID   TIME_ID      Cumulative Sum
----------    -------   ------       --------------
2             13        10-JAN-98    1205.99
2             13        16-JAN-98    2335.03
2             13        11-FEB-98    4089.16
...

此查询的结果证明是可以的,但是缺少一件事。

当没有销售交易时,不会显示日期的累计金额。

我需要的是以下结果:

CHANNEL_ID    PROD_ID   TIME_ID      Cumulative Sum
----------    -------   ------       --------------
2             13        10-JAN-98    1205.99
2             13        11-JAN-98    1205.99
2             13        12-JAN-98    1205.99
2             13        13-JAN-98    1205.99
...
...
2             13        16-JAN-98    2335.03
2             13        17-JAN-98    2335.03
2             13        18-JAN-98    2335.03
...
...
2             13        11-FEB-98    4089.16
2             13        12-FEB-98    4089.16
...
...

2 个答案:

答案 0 :(得分:0)

您可以尝试以下查询吗?

WITH min_max_date 
     AS (SELECT Min(time_id) min_time_id, 
                Max(time_id) max_time_id 
         FROM   sales) -- fetch min and max dates 
, 
     all_dates 
     AS (SELECT To_char(DATE '2004-01-01' - ROWNUM - 1, 'YYYY-MM-DD') AS date_id 
         FROM   dual 
         CONNECT BY ROWNUM < max_time_id - min_time_id) 
-- generated dates between min and max dates 
SELECT t2.channel_id, 
       t2.prod_id, 
       t1.date_id, 
       SUM(Nvl(amount_sold, 0)) 
         over ( 
           PARTITION BY channel_id, prod_id 
           ORDER BY t1.date_id) 
FROM   all_dates t1 
       left outer join sales t2 
                    ON t1.date__id = t2.time_id; 

答案 1 :(得分:0)

请看看这是否有效:

with data_table1 as (
select 2 channel_id, 13 prod_id, trunc(sysdate,'YY')+rownum+mod(rownum,6)-2 time_id, 1000*rownum amount_sold from dual connect by level <=10
)
select * from data_table1;
<头>
CHANNEL_ID PROD_ID TIME_ID AMOUNT_SOLD
2 13 01-JAN-21 1000
2 13 03-JAN-21 2000
2 13 05-JAN-21 3000
2 13 07-JAN-21 4000
2 13 09-JAN-21 5000
2 13 05-JAN-21 6000
2 13 07-JAN-21 7000
2 13 09-JAN-21 8000
2 13 11-JAN-21 9000
2 13 13-JAN-21 10000
with data_table1 as (
select 2 channel_id, 13 prod_id, trunc(sysdate,'YY')+rownum+mod(rownum,6)-2 time_id, 1000*rownum amount_sold from dual connect by level <=10
),
date_table2 as (select trunc(sysdate,'YY')+rownum-1 TIME_ID from dual connect by level <=(select max(time_id)-min(time_id)+1 from data_table1))
Select distinct CHANNEL_ID, PROD_ID, TIME_ID, SUM (nvl(AMOUNT_SOLD,0)) OVER (PARTITION BY CHANNEL_ID, PROD_ID ORDER BY TIME_ID) AS "Cumulative Sum" 
from data_table1 partition by (channel_id,PROD_ID) right join date_table2 using (TIME_ID)
Order By CHANNEL_ID ASC, PROD_ID ASC, TIME_ID ASC;

<头>
CHANNEL_ID PROD_ID TIME_ID 累计和
2 13 01-JAN-21 1000
2 13 02-JAN-21 1000
2 13 03-JAN-21 3000
2 13 04-JAN-21 3000
2 13 05-JAN-21 12000
2 13 06-JAN-21 12000
2 13 07-JAN-21 23000
2 13 08-JAN-21 23000
2 13 09-JAN-21 36000
2 13 10-JAN-21 36000
2 13 11-JAN-21 45000
2 13 12-JAN-21 45000
2 13 13-JAN-21 55000