2017-10-11 9 views
4

나는 그들이 할 수있는 활동을 기반으로 고객의 이탈을 계산하려고 시도하고 있으며, 이는 정상적인 날짜 인 이탈로 반대합니다. 우리는 특정 호스트에 연결된 이벤트를 가지고 있습니다. 예를 들어 모든 이벤트는 Alice가 호스팅하지만 다른 호스트 일 수 있습니다.공백 채우기, 이벤트 기반

특정 이벤트를 따르는 모든 사람들은 카테고리 (신규, 활성, 변경 및 부활)에 배치되어야합니다.

신규 : 처음 특정 사람이 특정 호스트의 이벤트를 수행합니다.
활성 : 다시 따르십시오 (특정 호스트의 마지막 이벤트도 따라했습니다).
휘젓다 : 추종자는 따라 할 기회가 있었지만하지 않았습니다.
부활 됨 : 추종자가 이전에 추적 한 호스트를 따라하기 시작했습니다.

declare @events table (event varchar(50), host varchar(50), date date) 
declare @eventFollows table (event varchar(50), follower varchar(50)) 

insert into @events values ('e_1', 'Alice', GETDATE()) 
insert into @events values ('e_2', 'Alice', GETDATE()) 
insert into @events values ('e_3', 'Alice', GETDATE()) 
insert into @events values ('e_4', 'Alice', GETDATE()) 
insert into @events values ('e_5', 'Alice', GETDATE()) 

insert into @eventFollows values ('e_1', 'Bob') --new 
insert into @eventFollows values ('e_2', 'Bob') --active 
--Bob churned 
insert into @eventFollows values ('e_4', 'Megan') --new 
insert into @eventFollows values ('e_5', 'Bob') --resurrected 
insert into @eventFollows values ('e_5', 'Megan') --active 

select * from @events 
select * from @eventFollows 

예상되는 결과는 내가 다음과 같은의 질의 시작이

select 'e_1', 1 as New, 0 as resurrected, 0 as active, 0 as churned --First time Bob follows Alice event 
union all 
select 'e_2', 0 as New, 0 as resurrected, 1 as active, 0 as churned --Bob follows the next event that Alice host (considered as Active) 
union all 
select 'e_3', 0 as New, 0 as resurrected, 0 as active, 1 as churned --Bob churns since he does not follow the next event 
union all 
select 'e_4', 1 as New, 0 as resurrected, 0 as active, 0 as churned --First time Megan follows Alice event 
union all 
select 'e_5', 0 as New, 1 as resurrected, 1 as active, 0 as churned --Second time (active) for Megan and Bob is resurrected 

같은 것을해야하지만, 문제는 내가 추종자하지 않았다 모든 이벤트를하지 않는다는 것입니다 따라 가라.

select a.event, follower, date, 
    LAG (a.event,1) over (partition by a.host, ma.follower order by date) as lag, 
    LEAD (a.event,1) over (partition by a.host, ma.follower order by date) as lead, 
    LAG (a.event,1) over (partition by a.host order by date) as lagP, 
    LEAD (a.event,1) over (partition by a.host order by date) as leadP 
from @events a left join @eventFollows ma on ma.event = a.event order by host, follower, date 

아이디어가 있으십니까?

+0

"churned"이후에는 어떻게됩니까? 그들은 한 번 휘젓다거나 휘젓다? – gbn

+0

깃발은 1 인당 또는 몇 명입니까? – gbn

+0

휘젓다가 다시 부활하면 다시 휘젓다 다. 내 예에서 Bob은 (이벤트 3과 이벤트 4를 제외하고) 이벤트 5에서 부활하지만, 이벤트 5에서 부활합니다. – corpat

답변

1

일치하지만, 숫자에 차이를 확인하여 섬을 검출 할 수있다 :

;with nrsE as 
(
    select *, ROW_NUMBER() over (order by event) rnrE from @events 
), nrs as 
(
    select f.*,host, rnrE, ROW_NUMBER() over (partition by f.follower, e.host order by f.event) rnrF 
    from nrsE e 
    join @eventFollows f on f.event = e.event 
), f as 
(
    select host, follower, min(rnrE) FirstE, max(rnrE) LastE, ROW_NUMBER() over (partition by follower, host order by rnrE - rnrF) SeqNr 
    from nrs 
    group by host, follower, rnrE - rnrF --difference between rnr-Event and rnr-Follower to detect gaps 
), stat as --from the result above on there are several options. this example uses getting a 'status' and pivoting on it 
(
    select e.event, e.host, case when f.FirstE is null then 'No participants' when f.LastE = e.rnrE - 1 then 'Churned' when rnrE = f.FirstE then case when SeqNr = 1 then 'New' else 'Resurrected' end else 'Active' end Status 
    from nrsE e 
    left join f on e.rnrE between f.FirstE and f.LastE + 1 and e.host = f.host 
) 
select p.* from stat pivot(count(Status) for Status in ([New], [Resurrected], [Active], [Churned])) p 

마지막 2 단계가 단순화 될 수 있지만 '상태'를 다른 방식으로 다시 사용할 수 있습니다.

0

이이 간접 접근 방식의 비트를 보일 수 있습니다 원하는 결과

SELECT 
    X.event, X.host, X.date, 
    IsNew = SUM(CASE WHEN X.FirstFollowerEvent = X.event THEN 1 ELSE 0 END), 
    IsActive = SUM(CASE WHEN X.lagFollowerEvent = X.lagEvent THEN 1 ELSE 0 END), 
    IsChurned = SUM(CASE WHEN X.follower IS NULL THEN 1 ELSE 0 END), 
    IsResurrected = SUM(CASE WHEN X.lagFollowerEvent <> X.lagEvent AND X.FirstFollowerEvent IS NOT NULL THEN 1 ELSE 0 END) 
FROM 
    (
    select 
     a.event, a.host, ma.follower, a.date, 
     FIRST_VALUE(a.event) over (partition by a.host, ma.follower order by a.date, a.event) as FirstFollowerEvent, 
     LAG (a.event,1) over (partition by a.host, ma.follower order by a.date, a.event) as lagFollowerEvent, 
     LAG (a.event,1) over (partition by a.host order by a.date, a.event) as lagEvent 
    FROM 
     @events a 
     LEFT join 
     @eventFollows ma on a.event = ma.event 
    ) X 
GROUP BY 
    X.event, X.host, X.date 
ORDER by 
    X.event, X.host, X.date 
+0

감사! 그러나 몇 가지 문제가 있습니다. 먼저 IsNew를 'IsNew = SUM (X.FirstFollowerEvent = X.event AND X.follower IS NOT NULL THEN 1 ELSE 0 END.)', ' 으로 변경해야합니다.하지만 내가 cu를 e_2에 추가하면 I 그 e_3에 휘젓다 것으로 예상하지만, e_3의 수는 단지 @eventFollows 값에 1 '삽입 ('e_2', '쿠퍼') '입니다 유사한 문제는 내가 추가하면 누군가가 내가 기대하는 e_1하는 것입니다 e_2에서 휘젓다면 e_2의 휘젓기 열은 여전히 ​​0입니다. 예를 들어. '@eventFollows 값 ('e_1', 'Donald')에 삽입하십시오. – corpat

+0

@corpat : 곧 답변을 업데이트 할 것입니다. – gbn