将数据集从切换状态转换为有效/有效日期

时间:2019-07-10 14:01:24

标签: sql

我们有一个功能表:

cust_no, cust_loc, feature, toggle, last_udpated_dt
123      ABC       DELIVER  Y       2019-01-01
123      ABC       DELIVER  Y       2019-01-03
123      ABC       DELIVER  N       2019-05-01
123      ABC       KEYS     N       2019-01-01
123      DEF       KEYS     N       2019-01-01
123      GHI       KEYS     N       2019-01-01
123      GHI       KEYS     Y       2019-02-01
123      GHI       KEYS     Y       2019-02-04
123      GHI       KEYS     N       2019-04-01
123      GHI       KEYS     Y       2019-06-01

有一个后端系统,它为Y / N不同的客户/位置设置了针对不同功能的切换。有效值是last_updated_dt最大的值;

我应该添加,我们经常将'重置'切换到其当前值,因此,如果有人进来并为客户关闭了所有功能/位置,则将为所有功能位置设置标志,即使那些没有位置的标志也将被设置设置,以及关闭的设置;

现在,我被要求评估一段时间内的性能,并且我需要知道何时打开和关闭功能。

我认为最好通过创建这样的表来实现:

cust_no, cust_loc, feature, effective_dt, expiration_dt
123      ABC       DELIVER  2019-01-01    2019-05-01
123      GHI       KEYS     2019-02-01    2019-04-01
123      GHI       KEYS     2019-06-01    9999-12-31

我们可以忽略ABC和DEF中的KEYS标志,因为它们从未打开过。

该种子行将带有最小last_updated_dt:

create table tmp_01 as
select cust_no, cust_loc, feature, min(last_updated_dt) as eff_dt
from feature
where toggle = 'Y'
group by cust_no, cust_loc, feature;

然后我创建一个特征表的副本,其中不包含任何这些行(或第一个Y之前的N个值)

create table tmp_02 as
select cust_no, cust_loc, feature, toggle, last_update_dt
from feature as f
, tmp_01 as a
where a.cust_no = f.cust_no 
and a.cust_loc = f.cust_loc 
and a.feature = f.feature 
and f.last_updated_dt <= eff_dt;

然后我可以在最小last_udated_dt处为每一行创建到期时间,其中toggle = N,创建一个没有这些行的新表

create table tmp_03 as
with f as (select cust_no, cust_loc, feature, min(last_updated_dt) as exp_dt
   from tmp_02
   where toggle = 'N'
   group by cust_no, cust_loc, feature
  )
select a.cust_no, a.cust_loc, a.feature, a.eff_dt
, min(coalesce(f.last_updated_dt,'9999-12-31')) as exp_dt
from tmp_01 as a
left outer join f
on (a.cust_no = f.cust_no 
   and a.cust_loc = f.cust_loc 
   and a.feature = f.feature) 
 ;

创建功能表(tmp_02)的副本,删除已使用的行:

create table tmp_04 as
select cust_no, cust_loc, feature, toggle, last_update_dt
from tmp_02 as f
, tmp_03 as a
where a.cust_no = f.cust_no 
and a.cust_loc = f.cust_loc 
and a.feature = f.feature 
and f.last_updated_dt <= exp_dt; 

现在tmp_03有了我想要的数据,但是只有第一个开/关周期;我将不得不在每个开/关周期重复此操作,直到没有剩余的行了。

似乎应该有一个方法可以在一个周期内完成此操作?我只是看不到。

2 个答案:

答案 0 :(得分:0)

我认为lead()是您想要的:

select t.*,
       last_updated_dt as eff_dt,
       lead(last_updated_dt) over (partition by cust_no, cust_loc, feature order by last_updated_dt) as end_dt
from t;

这应该为您提供所需的拼贴。

答案 1 :(得分:0)

就像很多问题一样,思考它,然后沉迷于其中。

这是我想出的。 它需要五个步骤,但是无论打开或关闭标志多少次都可以使用。

首先使用英语:

1,我们需要删除多余的行,在这些行中将标志重置为它已经具有的值。

2,如果第一个操作将标志设置为N,则我们将删除所有行

3,我们添加行号,并按字段添加组,以便每对Y / N都可以转换为eff_date,exp_date。

现在输入代码:

create table mww_001 as
select cust_no, cust_loc, feature, toggle, last_updated_date
, lag(toggle_value) over (partition by cust_no, cust_loc, feature 
                          order by last_updated_date) as lag_toggle
from feature_table;

create table mww_002 as 
select cust_no, cust_loc, feature, toggle, last_updated_date, lag_toggle
, row_number() over (partition by cust_no, cust_loc, feature
                     order by last_updated_date) as rownbr_01
from mww_001
where lag_toggle is null or lag_toggle <> toggle;

create table mww_003 as
select cust_no, cust_loc, feature, toggle, last_updated_date
, row_number() over (partition by cust_no, cust_loc, feature
                     order by last_updated_date) as rownbr_02
from mww_002
where not(rownbr_01 = 1 and toggle = 'N') ;

create table mww_003 as
select cust_no, cust_loc, feature, toggle, last_updated_date
, ceiling(rownbr_02/2) as group_01
from mww_002 ;

create table feature_new as
select cust_no, cust_loc, feature, group_01
, max(case when toggle = 'Y' then last_updated_date else null end) as eff_dt
, coalesce(max(case when toggle = 'N' 
                    then last_updated_date 
                    else null end)
           , '9999-12-31') as exp_dt
from mww_003 
group by cust_no, cust_loc, feature, group_01 ;