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

Finding first of consecutive dates using analytical functions

我需要分析存储在一个 Oracle 数据库中的一段数据 table。 table 中的示例行是这样的:

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

每个部门和每个日期各占一行。我想要的是,对于任何给定日期的每个部门,找到该日期之前 Status 为 0 的第一个日期。例如,对于部门D1,对于2016/6/1,结果是2015/5/30,对于D1,2016/5/31和5/30也是2015/5/30。对于D1,2016/5/29和5/28是2016/5/28.

我需要将结果输出为 SELECT 结果并将其存储在另一个 table 中。所以结果 table 与原始 table 的行数完全相同。结果table中大概有三列:DepartmentDateTargetDate.

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

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_ (我添加了下划线)。