2014-10-06 2 views
0

T-SQL에서 복잡한 쿼리를 작성하고 있습니다. 그래서 내가 가지고 내가 가진 데이터 세트는 하나의 테이블 (의이 Table T를 호출하자를)이며, 데이터는동일한 데이터 집합의 다중 조인

| Happened    | Contributor | Status | Direction | Purchased | 
|-------------------------|-------------|--------|-----------|-----------| 
| 2014-10-06 01:00:00.000 | A   | 0  | NULL  | NULL  | 
| 2014-10-06 02:00:00.000 | A   | 1  | NULL  | NULL  | 
| 2014-10-06 03:00:00.000 | A   | 2  | inbound | NULL  | 
| 2014-10-06 04:00:00.000 | A   | 0  | NULL  | yes  | 
| 2014-10-06 05:00:00.000 | A   | 2  | outbound | yes  | 
| 2014-10-06 06:00:00.000 | B   | 2  | inbound | NULL  | 

같이

  • 의 원인 일 (T.Happened)와 피사체의 고유 쌍 이벤트 (T.Contributor);
  • 이벤트가 발생한 순간의 상태.
  • 어떤 방향으로 인바운드 또는 아웃 바운드가 될 수 있습니다 (boolean-ish 열).
  • 일부 구매 표시 (이전과 동일).

는 내가 필요로하는 각 별개의 기여를 위해, 선택, 쿼리입니다

    상태가 0에서 1로 변경되었습니다
  • 빠른 날짜;
  • 상태가 0이 아닌 가장 빠른 datetime 및 T.Direction = 'inbound'; 이벤트의
  • T.Purchased = 'yes' 상태가 0

하지 않고 행의 다른 필드가 비어있는 경우에도 참여자의 전체 집합을 표시합니다. 내가 뭘하려

가 난 후 그 결과 데이터 세트가
| Contributor | StatusChangedFrom0To1 | StatusWasNot0AndDirectionWasInbound | StatusWasNot0AndPuchasedWasYes | 
|-------------|-------------------------|-------------------------------------|--------------------------------| 
| A   | 2014-10-06 02:00:00.000 | 2014-10-06 03:00:00.000    | 2014-10-06 05:00:00.000  | 
| B   | NULL     | 2014-10-06 06:00:00.000    | NULL       | 
가 어떤 방법 내가 따라야

내가 얻을 어떤 방향을 발굴해야

과 같아야 만

... 
FROM Table T 
JOIN Table T2 ON 
    (T.Contributor = T2.Contributor 
    AND T.Happened < T2.Happened 
    AND T2.Status = 1 
    AND T1.Status = 0) 
JOIN Table T3 ON 
... 

같은 조인 여러했다 결과는 원하는가? 특정 유형의 참여 (예 : 완전 외부 참여)를 사용해야합니까?

나는 MS SQL Server 2008을 사용하고 있는데, 나는 "엔터프라이즈 및 물건"이라는 이유로이 버전에 묶여 있기 때문에 새로운 버전으로 업그레이드하는 것이 쉽지 않습니다. 나는 상태 만 증가한다고 가정하면

+0

사용하는 SQL 서버의 어떤 버전 :

상관 하위 쿼리의 모습? –

+0

MS SQL Server 2008. –

답변

1

는, 상태가 0에서 1로 변경 빠른 시간이 상태가 1 이른 시간이다 (이 질문에 샘플 데이터의 사실이다) :

select contributor, 
     min(case when status = 1 then happened end) as StatusChangedFrom0To1, 
     min(case when status <> 0 and direction = 'inbound' then happened end) as StatusWasNot0AndDirectionWasInbound, 
     min(case when status <> 0 and purchased = 'yes' then happened end) as StatusWasNot0AndPuchasedWasYes, 
     sum(case when status <> 0 and purchased = 'yes' then 1 else 0 end) as cnt 
from table t 
group by contributor; 

StatusChangedFrom0To1에 대한 가정이 사실이 아닌 경우 쿼리를 조건부 집계로 계속 사용할 수 있지만이 변수를 가져 오기 위해 추가 작업이 필요합니다. SQL 서버 2012+, 당신은이 목적을 위해 lag()를 사용할 수 있습니다

select contributor, 
     min(case when status = 1 and prevstatus = 0 then happened end) as StatusChangedFrom0To1, 
     min(case when status <> 0 and direction = 'inbound' then happened end) as StatusWasNot0AndDirectionWasInbound, 
     min(case when status <> 0 and purchased = 'yes' then happened end) as StatusWasNot0AndPuchasedWasYes, 
     sum(case when status <> 0 and purchased = 'yes' then 1 else 0 end) as cnt 
from (select t.*, lag(status) over (partition by Contributor order by happened) as prevstatus 
     from table t 
    ) t 
group by contributor; 

이전 버전에서는, 나는 동일한 기능에 대한 상관 하위 쿼리를 사용합니다.

편집 :

from (select t.*, 
      (select top 1 t2.status 
       from table t2 
       where t.contributor = t2.contributor and t2.happened < t.happened 
       order by t2.happened desc 
      ) as prevstatus 
     from table t 
    ) t 
+0

MSDN에서 LAG() 함수 참조는 "SQL Server 2014에서 자체 조인을 사용하지 않고 동일한 결과 집합의 이전 행에서 데이터에 액세스합니다."라고 말합니다. 하지만 MS SQL Server 2008에 제약이 있다면 어떻게해야합니까? 필자는 실제로 조인을 사용하여 추가적인 가짜 열이있는 테이블을 작성해야합니까? 아니면'select ... from (select ...) '를 더 자세히 살펴 봐야합니까? –

+0

맞습니다. 제 서버에서'LAG()'가 작동하지 않았습니다. 하위 쿼리 솔루션을 제공하게되어 기쁩니다. 그것은 많은 도움이되었습니다, 감사합니다! –