使用分析函数查找第一个连续日期
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中大概有三列:Department
、Date
、TargetDate
.
我在 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_ (我添加了下划线)。
我需要分析存储在一个 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中大概有三列:Department
、Date
、TargetDate
.
我在 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_ (我添加了下划线)。