SQL Connect子句 - 按日期生成所有数据

时间:2017-08-21 18:06:29

标签: sql oracle connect-by

表格中的数据按生效日期存储。你能帮我一个ORACLE SQL语句,它将8/1数据复制到8 / 2,8 / 3,8 / 4并在之后重复8/5值吗?

DATE             VALUE1    VALUE2    
8/1/2017           x         1  
8/1/2017           x         2   
8/7/2017           y         4  
8/7/2017           x         3  

期望的输出:

DATE             VALUE1     VALUE2  
8/1/2017           x          1  
8/1/2017           x          2  
8/2/2017           x          1  
8/2/2017           x          2  

...重复到8/6

8/7/2017           y         4  
8/7/2017           x         3  
8/8/2017           y         4  
8/8/2017           x         3  

...重复到sysdate - 1

2 个答案:

答案 0 :(得分:0)

您想要使用LAST_VALUE分析函数,如下所示:

 select 
   fakedate,
   CASE 
     WHEN flip=1 THEN 
       LAST_VALUE(yourvalue1rown1 IGNORE NULLS) OVER(ORDER BY fakedate) 
     ELSE
       LAST_VALUE(yourvalue1rown2 IGNORE NULLS) OVER(ORDER BY fakedate) 
   END as lastvalue1,
   CASE 
     WHEN flip=1 THEN 
       LAST_VALUE(yourvalue2rown1 IGNORE NULLS) OVER(ORDER BY fakedate) 
     ELSE
       LAST_VALUE(yourvalue2rown2 IGNORE NULLS) OVER(ORDER BY fakedate) 
   END as lastvalue2    
 from

 select
   fakedate, flip,
   CASE WHEN rown = 1 THEN yourvalue1 END as yourvalue1rown1,
   CASE WHEN rown = 2 THEN yourvalue1 END as yourvalue1rown2,
   CASE WHEN rown = 1 THEN yourvalue2 END as yourvalue2rown1,
   CASE WHEN rown = 2 THEN yourvalue2 END as yourvalue2rown2
 from
   (select (sysdate - 100) + trunc(rownum/2) fakedate, mod(rownum, 2)+1 as flip from dual connect by level <= 100) fakedates
   left outer join
   (select yt.*, row_number() over(partition by yourdate order by yourvalue1) as rown) yourtable
   on
     fakedate = yourdate and flip = rown 

您必须调整列名以匹配您的表。您还必须调整100以反映您需要多长时间才能到达日期数据的开头。

请注意这是未经测试的(SQLFiddle在我的妈妈身上有一些oracle问题)所以如果你得到任何语法错误或其他一些你无法解决的小问题,请发表评论,我会解决这些问题

答案 1 :(得分:0)

这是一种方法。它不是最优雅或最有效的,但它是我能想到的最基本的方式(缺少真正低效的东西,如相关子查询,不能轻易地解开连接)。

在第一个子查询中,别名为a,我创建了所有需要的日期。在第二个子查询b中,我创建了日期范围,我们将需要重复特定的行(在测试数据中,我允许必须重复的行数变为可变行)问题的微妙之处更加明显。)

有了这些,通过连接这两个子查询和原始数据很容易得到结果。唉,这种方法需要读取基表三次;希望你没有太多的数据需要处理。

with
     inputs ( dt, val1, val2 ) as (
       select date '2017-08-14', 'x', 1 from dual union all
       select date '2017-08-14', 'x', 2 from dual union all
       select date '2017-08-17', 'y', 4 from dual union all
       select date '2017-08-17', 'x', 3 from dual union all
       select date '2017-08-19', 'a', 5 from dual
     )
-- End of simulated inputs (for testing purposes only, not part of the solution).
-- Use your actual table and column names in the SQL query below.
select a.dt, i.val1, i.val2
from   (
         select min_dt + level - 1 as dt
         from   ( select min(dt) as min_dt from inputs )
         connect by level <= sysdate - min_dt
       ) a
       join
       (
         select dt, lead(dt, 1, sysdate) over (order by dt) as lead_dt
         from   (select distinct dt from inputs)
       ) b
         on a.dt >= b.dt and a.dt < b.lead_dt
       join
       inputs i on i.dt = b.dt
order by dt, val1, val2
;

<强>输出:

DT         VAL1 VAL2
---------- ---- ----
2017-08-14 x       1
2017-08-14 x       2
2017-08-15 x       1
2017-08-15 x       2
2017-08-16 x       1
2017-08-16 x       2
2017-08-17 x       3
2017-08-17 y       4
2017-08-18 x       3
2017-08-18 y       4
2017-08-19 a       5
2017-08-20 a       5