2013-02-08 50 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 

下面是oracle的代碼,我在工作(與谷歌的幫助),但我不是因爲得到正確的結果重疊的日期。我請求專家幫助我解決這個問題。 (在此先感謝)

當前結果:

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

ORACLE 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月至2010年10月)。我不太確定問題是什麼......您確定您的示例數據是您實際使用的內容(不僅僅是因爲列名使用您的「標籤」別名)。 – 2013-02-08 18:10:00

+0

嗨亞歷克斯..謝謝你審查的代碼。我在這裏找到的問題是,在1月10日的月份,收入僅由帳戶ID「1234」生成,但該查詢的結果顯示2並且相似,對於2月份,收入由Account Ids的1234「和「4567」,但查詢顯示3。我完全不確定原因。你能幫我嗎? .. – Jay 2013-02-08 19:09:04

+0

但是,當我用你的三行數據創建一個'accounts'表時,你的查詢給我'1,2,2,1,1,1'的預期。這張圖片中缺少一些東西...... – 2013-02-08 19:29:38

回答

0

這是我花了一段時間,看看爲什麼你認爲有問題。使用您提供的原始三行數據,運行您的查詢可以準確得出您的「預期結果」。隨着54列從您的CSV文件中的數據,結果是48行(涵蓋四年),從2010年1月非零總數到2013年1月返回的前幾行是:

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

但是,看起來是正確的:

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 

但我想你想要的是不是真正的問題強調的:「讓的客戶積極的」。假設由「客戶」你的意思是唯一帳戶ID,你只需要修改計數:

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 

你做錯了什麼試圖在您的tab子查詢中應用distinct;但不同的返回不同的行,並且由於日期不同,實際上並沒有減少返回的行數。

這還不完全符合您的預期結果,但看起來與數據相符(如果我對您想要的是正確的假設),並且仍然會爲您提供三行樣本的預期結果。


另一種方式來編寫查詢,我覺得這有點容易跟蹤,並使用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 2013-02-08 23:08:41