2013-02-08 2 views
-1

수익 기여 기간을 기준으로 한 달에 활동중인 고객 수를 얻으라는 요구가 있습니다.날짜 범위의 활성 ID

원본 데이터 :

ACCOUNT_ID REVENUE_START_DATE  REVENUE_END_DATE 
1234   1/14/2010 0:00   4/13/2010 23:59 
4567   2/9/2010 0:00   3/8/2010 23:59 
1234   5/9/2010 0:00   6/8/2010 23:59 

예상 결과 아래

Month Count 
Dec-09 0 
Jan-10 1 
Feb-10 2 
Mar-10 2 
Apr-10 1 
May-10 1 
Jun-10 1 
Jul-10 0 
Aug-10 0 
Sep-10 
Oct-10 

내가 (구글의 도움으로)에 근무 오라클 코드 그러나 나는 인해 올바른 결과를 얻고 있지 않다 겹치는 날짜. 나는 전문가에게이 일을 도와 줄 것을 요청한다. (미리 감사드립니다)

현재 결과 :

YEAR_ MONTH_ ACT 
2010 January  2 
2010 February 3 
2010 March  3 
2010 April  3 

오라클 CODE : 그것은 나에게 동안을 촬영하고

with tab as 
(
    select distinct ACCOUNT_ID, billing_start_date as revenue_start_date, billing_end_date as revenue_end_date 
    from accounts 
       ),      
    year_tab as 
       (
        select 
          add_months(min_date, level -1) m 
        from 
          (
          select min(trunc(revenue_start_date,'YYYY')) min_date, add_months(max(trunc(revenue_end_date,'YYYY')), 12) max_date 
          from tab 
          ) 
        connect by level <= months_between(max_date, min_date) 
      )  
select to_char(m,'YYYY') year_, 
     to_char(m,'Month') month_, 
     nvl(act, 0) act 
from year_tab, 
      (   
      select m date_,count(*) act 
      from tab, year_tab 
      where m between trunc(revenue_start_date,'MM') and trunc(revenue_end_date,'MM') 
      group by m 
      ) month_tab 
where m = date_(+) 
order by m; 
+0

2010 년의 모든 달을 보여줍니다 , 2009 년 12 월 ~ 2009 년 10 월). 질문이 무엇인지 확신 할 수 없습니다 ... 샘플 데이터가 실제로 사용하고 있는지 확신합니까 (컬럼 이름이'탭 '별명을 사용하고 있기 때문에). –

+0

안녕하세요 Alex .. 코드를 검토해 주셔서 감사합니다. 여기서 발견 한 문제는 1 월 10 일에 수익이 계정 ID "1234"에 의해서만 생성되었지만이 쿼리의 결과는 2를 나타내고 2 월에는 계정 ID '1234'에 의해 수익이 생성된다는 것을 알 수 있습니다. 및 "4567"이지만 쿼리에 3이 표시됩니다.나는 이유가 확실하지 않습니다. 제발 저를 도울 수 있습니까? .. – Jay

+0

하지만 3 행의 데이터가있는'accounts' 테이블을 만들 때 쿼리는'1,2,2,1,1,1'을 예상대로 제공합니다. 이 그림에서 뭔가가 누락되었습니다 ... –

답변

0

당신은 문제가 있다고 생각하는 이유를 참조하십시오. 제공 한 원래의 3 행의 데이터로 쿼리를 실행하면 정확히 '예상 결과'를 얻을 수 있습니다.

YEAR_ MONTH_          ACT 
----- ------------------------------------ ---------- 
2010 January          2 
2010 February          3 
2010 March           3 
2010 April           3 
2010 May           2 

그러나 : CSV 파일에서 데이터의 54 행으로, 결과 월 2013 월 2010 비 제로의 합계와 (사년 커버) 48 개 행이 반환 처음 몇 행은이다 올바른 같습니다

select * from accounts 
where not (billing_start_date > date '2010-02-01' 
     or billing_end_date < date '2010-01-01'); 

ACCOUNT_ID BILLING_START_DATE BILLING_END_DATE 
---------- ------------------ ------------------ 
     1234 09/01/2010 00:00 08/02/2010 23:59 
     4567 14/01/2010 00:00 13/04/2010 23:59 

2 rows selected 

select * from accounts 
where not (billing_start_date > date '2010-03-01' 
     or billing_end_date < date '2010-02-01'); 

ACCOUNT_ID BILLING_START_DATE BILLING_END_DATE 
---------- ------------------ ------------------ 
     1234 09/01/2010 00:00 08/02/2010 23:59 
     4567 14/01/2010 00:00 13/04/2010 23:59 
     1234 09/02/2010 00:00 08/03/2010 23:59 

3 rows selected 

select * from accounts 
where not (billing_start_date > date '2010-04-01' 
     or billing_end_date < date '2010-03-01'); 

ACCOUNT_ID BILLING_START_DATE BILLING_END_DATE 
---------- ------------------ ------------------ 
     4567 14/01/2010 00:00 13/04/2010 23:59 
     1234 09/02/2010 00:00 08/03/2010 23:59 
     1234 09/03/2010 00:00 08/04/2010 23:59 

3 rows selected 

하지만 난 당신이 정말 문제에서 강조되지 않았다 싶어 생각을 '활성 고객의 수를 얻기 위해'.

select m date_,count(distinct account_id) act 
    from tab, year_tab 
    ... 

...로 처음 몇 행을 제공합니다 : 당신이 잘못하고 있었다 무엇

YEAR_ MONTH_          ACT 
----- ------------------------------------ ---------- 
2010 January          2 
2010 February          2 
2010 March           2 
2010 April           2 
2010 May           1 

는 고유의 계정 ID를 의미하는 '고객'으로, 당신은 단지 수를 수정해야한다고 가정 tab 하위 쿼리에 distinct을 적용하려고 시도했습니다. distinct는 별개의 행을 반환하고 날짜가 실제로는 반환되는 행의 수를 줄이지는 않았기 때문에 다릅니다.

예상 결과와 여전히 일치하지 않지만 데이터가 일치하는 것 같습니다 (원하는 내용에 대한 내 가정이 맞다면), 3 행 샘플에 대한 예상 결과가 여전히 제공됩니다.


내가 따라하기 좀 더 쉽게 찾을 쿼리를 작성하고, ANSI 구문 조인을 사용하는 또 다른 방법 : 나는 떨어져에서 (당신의 예상 결과를 얻을 수

with t as (
    select add_months(min_date, level - 1) month_start, 
     add_months(min_date, level) next_month_start 
    from (
     select trunc(min(billing_start_date),'YYYY') min_date, 
      add_months(trunc(max(billing_start_date),'YYYY'), 12) max_date 
     from accounts 
    ) 
    connect by level <= months_between(max_date, min_date) 
) 
select to_char(t.month_start,'YYYY') year_, 
    to_char(t.month_start,'Month') month_, 
    count(distinct a.account_id) act 
from t 
left join accounts a on not (billing_start_date > t.next_month_start 
    or billing_end_date < t.month_start) 
group by t.month_start 
order by t.month_start; 
+0

위대한 .. 이것은 내가 찾고있는 것입니다. 시간과 도움을 많이 주셔서 감사합니다. – Jay