使用分析函数查找连续日期的第一个

时间:2016-06-29 00:55:11

标签: oracle plsql data-analysis

我需要分析存储在一个Oracle数据库表中的一段数据。此表中的示例行如下所示:

Department  Date    Status
------------------------------------
D1          2016/6/1    1
D1          2016/5/31   0
D1          2016/5/30   0
D1          2016/5/29   1
D1          2016/5/28   0
D1          2016/5/27   1
D2          2016/6/1    0
D2          2016/5/31   1
D2          2016/5/30   1
D2          2016/5/29   0
D2          2016/5/28   0
D2          2016/5/27   1

每个部门和每个日期都有一行。我想要的是,对于任何GIVEN DATE的每个部门,找到Status在此日期之前为0的第一个日期。例如,对于2016/6/1的D1部门,结果是2015/5/30,对于D1,2016/5/31和5/30,它也是2015/5/30。对于D1,2016/5/29和5/28,它是2016/5/28。

我需要将结果输出为SELECT结果并将其存储在另一个表中。因此,结果表与原始表具有完全相同的行数。结果表中可能包含三列:DepartmentDateTargetDate

我对SQL / PL SQL没什么经验。我想我应该使用分析函数和窗口,但我真的无法提出查询。请给我一些建议。谢谢!

1 个答案:

答案 0 :(得分:3)

with test_data (department, date_, status) as (
       select 'D1', date '2016-06-01', 1 from dual union all
       select 'D1', date '2016-05-31', 0 from dual union all
       select 'D1', date '2016-05-30', 0 from dual union all
       select 'D1', date '2016-05-29', 1 from dual union all
       select 'D1', date '2016-05-28', 0 from dual union all
       select 'D1', date '2016-05-27', 1 from dual union all
       select 'D2', date '2016-06-01', 0 from dual union all
       select 'D2', date '2016-05-31', 1 from dual union all
       select 'D2', date '2016-05-30', 1 from dual union all
       select 'D2', date '2016-05-29', 0 from dual union all
       select 'D2', date '2016-05-28', 0 from dual union all
       select 'D2', date '2016-05-27', 1 from dual
     ),
     t (department, date_, status, lagged_status) as (
       select department, date_, status,
              lag(status) over (partition by department order by date_)
       from   test_data
     ) 
select   department, date_, 
         max(case when status = 0 and (lagged_status = 1 or lagged_status is null) 
                  then date_ end)
             over (partition by department order by date_
                   rows between unbounded preceding and current row) as target_date
from     t
order by department, date_ desc
;

结果:

DEPARTMENT  DATE_      TARGET_DATE
----------- ---------- -----------
D1          2016-06-01 2016-05-30
D1          2016-05-31 2016-05-30
D1          2016-05-30 2016-05-30
D1          2016-05-29 2016-05-28
D1          2016-05-28 2016-05-28
D1          2016-05-27 (null)
D2          2016-06-01 2016-06-01
D2          2016-05-31 2016-05-28
D2          2016-05-30 2016-05-28
D2          2016-05-29 2016-05-28
D2          2016-05-28 2016-05-28
D2          2016-05-27 (null)

12 rows selected.

请注意,“date”是Oracle关键字,不应用作列名;我使用了date_(我添加了一个下划线)。