2017-05-17 12 views
2

나는 ValidFromValidTo 날짜가있는 데이터가 있습니다. 간단히 설명하면 다음과 같습니다.T-SQL - 시간 경과에 따른 발생 횟수 추적

MembershipId | ValidFromDate | ValidToDate 
========================================== 
0001   | 1997-01-01 | 2006-05-09 
0002   | 1997-01-01 | 2017-05-12 
0003   | 2005-06-02 | 2009-02-07 

이 테이블에는 두 날짜를 키 값으로 포함하는 비 클러스터형 인덱스가 있습니다.

나는 또한 1900부터 2999까지의 모든 날짜를 다루는 날짜 차원 테이블을 가지고 있습니다.

Date 차원 테이블에서 날짜 범위를 선택할 수있는 방법을 알아 내려고 (이 경우 2016-01-01에서 2016-12-31으로 가정) 각 날짜에 해당 날짜에 유효한 멤버 수를 확인하십시오.

아래의 코드는 작업을 수행하지만 성능은 좋지 않으며 누구에게도이 문제를 해결할 수있는 더 좋은 방법이 있는지 궁금합니다.

SELECT 
    d.DateKey 
    ,(SELECT COUNT(*) FROM Memberships AS m 
    WHERE d.DateKey between m.ValidFromDateKey and m.ValidToDateKey 
    ) AS MembershipCount 

FROM  
    DIM.[Date] AS d 

WHERE 
    d.CalendarYear = 2016 

미리 제안 해 주셔서 감사합니다.

답변

4

SQL의 논리가 대부분 정확합니다. SQL을 사용하여 작업하는 방식이 잘못 구현되었습니다. 당신의 Dates 테이블을 시작으로 당신은 join에 로직을 변경하지 않고 데이터의 각 행에 대해 하위 선택을하는 것보다, 이미 수행하고 당신이 있기 때문에 :

select d.DateKey 
     ,count(m.MembershipID) as MembershipCount 
from DIM.[Date] as d 
    left join Memberships as m 
     on(d.DateKey between m.ValidFromDateKey and m.ValidToDateKey) 
where d.CalendarYear = 2016 
group by d.DateKey 
order by d.DateKey; 

당신이 할 수 있습니다 무엇 주의해야 할 점은 매일 회원수를 계산하는 것입니다. 예를 들어, 귀하의 날짜가 2006-05-09 일 경우 MembershipID 0001은 그날 종료 될까요?

질문은 본질적으로 에 활성 상태였던 회원 수를 하루 종일 계산합니까, 아니면 특정 시간에 활성화되었거나 시작일 또는 종료일 뿐인 회원 수입니까?

그런 다음 ValidFromDate 값에 대해이 생각 프로세스를 반복하십시오.

+0

환상적! 완벽하게 작동합니다 - 쿼리가 30 초 이상 걸리면 중단했지만 지금은 1 초 미만으로 전체 연도가 실행됩니다. 날짜에 대한 의견을 보내 주셔서 감사합니다. 회원 자격이 매일 유효하고 ValidTo/From 날짜가 포함되어 있는지 여부를 알아야 검색어가 표시됩니다. – triplestones

+0

와우! 이것이 당신에게 필요한 성과를 준다면, 그것은 좋은 방법입니다. 비 equijoin이 너무 오래 걸릴 때 다른 접근법이 있습니다. –

+0

@triplestones SQL은 데이터 집합을 사용하여 작동하므로 데이터 집합을 함께 결합하는 것이 좋습니다. 테이블은 단지 데이터 세트입니다. 메인'select' 안에 다른 select 문을 넣으면 리턴되는 모든 행에 대해 실행됩니다. 추가 읽기를 원하면 "Set Based Thinking"을 찾아보십시오 – iamdave