当前数据
100022946 02/11/2014 02/01/2015 Lapsed
100022946 02/01/2015 05/01/2015 Active
100022946 05/01/2015 11/01/2015 Active
100022946 29/06/2000 05/01/2015 Lapsed
100022946 04/07/2014 05/07/2014 Lapsed
100022946 05/07/2014 26/07/2014 Lapsed
100022946 26/07/2014 31/07/2014 Lapsed
100022946 31/07/2014 17/08/2014 Lapsed
100022946 17/08/2014 31/08/2014 Long
100022946 31/08/2014 07/09/2014 Active
100022946 07/09/2014 07/10/2014 Lapsing
预期数据 *请检查活动更改的起始日期和日期以生成逻辑/ *
100022946 02/11/2014 02/11/2014 Lapsed
100022946 02/01/2015 11/01/2015 Active
100022946 11/01/2015 17/08/2015 Lapsed
100022946 17/08/2015 31/08/2014 Long
100022946 31/08/2014 07/09/2014 Active
100022946 07/09/2014 07/10/2014 Lapsing
答案 0 :(得分:0)
我认为首先你需要一个索引,通过使用类似ROW_NUMBER() OVER (ORDER BY (SELECT null))
之类的内容来为你的数据订购,然后找回已更改的Activity
并返回该记录的下一个FromDate
然后你需要返回过滤未更改的记录后的前一个FromDate
;但是我会在第一行遇到一些问题,我用这样的UNION
处理它:
WITH t AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT null)) rn
FROM yourTable
), nt AS (
SELECT *,
CASE
WHEN Activity <> ISNULL(LEAD(Activity) OVER (PARTITION BY ID ORDER BY rn), '') THEN
ISNULL(LEAD(FromDate) OVER (PARTITION BY ID ORDER BY rn), 0)
END AS prevFromDate
FROM t
UNION ALL
SELECT ID,null,null,null, 1, FromDate
FROM t
WHERE rn = 1
)
SELECT ID, ISNULL(LAG(prevFromDate) OVER (PARTITION BY ID ORDER BY rn), FromDate) FromDate, ToDate, Activity
FROM nt
WHERE prevFromDate IS NOT NULL AND FromDate IS NOT NULL;
我还没有测试过。
答案 1 :(得分:0)
shA, here is the final answer
--Sample table creation Script
create table sesht(CUSTID int,fromdate date,activity char(1));
--Sample data
insert into sesht values (1,'01-JAN-2015' ,'A') ;
insert into sesht values (1,'05-JAN-2015' ,'A') ;
insert into sesht values (1,'10-JAN-2015' ,'B') ;
insert into sesht values (1,'12-JAN-2015' ,'B') ;
insert into sesht values (1,'15-JAN-2015' ,'B') ;
insert into sesht values (1,'16-JAN-2015' ,'A') ;
insert into sesht values (1,'20-JAN-2015' ,'C') ;
insert into sesht values (1,'22-JAN-2015' ,'C') ;
insert into sesht values (1,'24-JAN-2015' ,'C') ;
----Base table - work out next record and see if the data is chagnged and rownumber is assigned to every record
drop table seshtt ;
create table seshtt as
Select custid,fromdate,COALESCE(activity,'') Activity
,CASE
WHEN COALESCE(activity,'') <> COALESCE(LEAD(activity) OVER (PARTITION BY CUSTID ORDER BY rn),'') THEN
LEAD(FromDate) OVER (PARTITION BY CUSTID ORDER BY FromDate)
END AS prevFromDate
,rn
from
(
Select custid,fromdate, activity, ROW_NUMBER() OVER (PARTITION BY CUSTID ORDER BY FromDate) rn from sesht
)
;
Select aa.custid,aa.fromdate,(NULL) TODATE,activity,aa.rn from seshtt aa
join
(
select custid,max(rn)+1 rn from seshttt
group by custid
) bb
on aa.custid=bb.custid
and aa.rn=bb.rn;
select * from seshttt ;
----Build main records (First & last records are not sorted)
create table seshttt as
SELECT custid, COALESCE(LAG(prevFromDate) OVER (PARTITION BY CUSTID ORDER BY fromdate), FromDate) FromDate, prevFromDate ToDate, Activity,rn
FROM seshtt
WHERE prevFromDate IS NOT NULL AND FromDate IS NOT NULL;
----Last record is now sorted & it becomes main table where first record will need to be updated
create table seshtttt as
Select * from seshttt
UNION ALL
Select aa.custid,aa.fromdate,(NULL) TODATE,activity,aa.rn from seshtt aa
join
(
select custid,max(rn)+1 rn from seshttt
group by custid
) bb
on aa.custid=bb.custid
and aa.rn=bb.rn;
select * from seshtttt;
---First record is sorted from both tables and rowid is used to merge the dataset;
create table seshtttttt as
Select src.*,bb.fromdate srcdate from
(
Select aa.custid,aa.fromdate,aa.rowid rwid from seshtttt aa join
(
Select custid,min(rn) rn from seshtttt group by custid
) bb
on aa.custid=bb.custid and aa.rn=bb.rn
) src
join
(
Select custid,fromdate from seshtt where rn=1
) bb
on src.custid=bb.custid;
select * from seshtttttt ;
---Merge runs here
merge into seshtttt tgt
using seshtttttt src
on
(tgt.rowid=src.rwid
and tgt.custid=src.custid)
when
matched then
update set tgt.fromdate=src.srcdate;
commit;
select * from seshtttt ;
1. List item