2016-10-13 6 views
0

のは、私は次のようなデータを持っているとしましょう:要約値

ContactDate Zip 
10-1-2016 90210 
10-7-2016 90211 
10-8-2016 90210 
10-8-2016 90211 

私は30日の期間中に郵便番号ごとに発生した連絡先の数を合計します。ただし、月単位ではなく、月単位の請求日となります。だから私は、次のような結果を取得しようとしている

...その日は各月の第2回であると言うことができます:

BillingMonthStart Zip Count 
9-2-2016   90210 1 
10-2-2016   90210 1 
10-2-2016   90211 2 

はここに私の試みですが(明らかにテーブル構造が異なっている、私は始めましょう)上記の例を修正:ここ

select 
    C1.ContactDate, count(C1.ContactDate) 
from 
    dbo.contacts c1 join dbo.contacts C2 on 
     C2.contactdate between C1.ContactDate AND dateadd(day, 30, C1.ContactDate) 
     AND c1.account = c2.accountid 
    join payment.dbo.AccountBilling B on c1.accountid = B.AccountID 
where 
    c1.account = @accountid 
    and C1.ContactDate >= @start_date 
    and C1.ContactDate <= @end_date 
    and DAY(C1.ContactDate) = B.BillingDOM 
Group by C1.contactDate 

問題は、アカウントが課金日に接触を取得した場合、私は文句を言わない、その月の結果を得ることです。

EDIT 最初に、不適切な形式の質問を申し訳ありません。私はそれを理解しました(私は確かに良い方法があると確信しています)。ここに私がやったことだ:

  1. betweenを使用して連絡先データテーブルに参加(約私が世話範囲内で)私は、すべての請求日発生した再帰CTEを使用して、変数
  2. に請求月取得#2とbillingDate + 1月の請求日
  3. グループを請求日までにグループ化し、 を選択します。ここで

はSQLです:

DECLARE @start_date DateTime 
DECLARE @end_date DateTime 
DECLARE @accountid int 
DECLARE @billing_dom tinyint 

SET @start_date = '2016-01-01' 
SET @end_date = '2016-12-31' 
SET @accountid = 6045032; 

select @billing_dom = BillingDOM 
from Payment.dbo.AccountBilling 
where AccountID = @accountid; 


WITH cte_months AS 
(
    SELECT 
     BillingDate = CAST(CAST(datepart(yyyy, @start_date) AS varchar) + '-' + CAST(datepart(mm, @start_date) AS varchar) + '-' + CAST(@billing_dom AS varchar) AS DATETIME), 
     dt = @start_date 
    UNION ALL 
    SELECT 
     BillingDate = DateAdd(mm, 1, BillingDate), 
     dt = DATEADD(mm, 1, dt) 
    FROM 
     cte_months 
    WHERE 
     dt < DATEADD(mm, -1, @end_date) 
) 
--SELECT * FROM cte_months 


select 
    cte_months.BillingDate, count(C.ContactDate) as Contacts 
from 
    cte_months left join dbo.contacts C on 
     C.ContactDate between cte_months.BillingDate and dateadd(mm, 1, cte_months.BillingDate) 
where 
    C.accountid = @accountid 
Group by cte_months.BillingDate 
+1

ここでは、開始するには絶好の場所です。 http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

+0

90210の9-2-2016カウントが1であることを説明できますか? –

+0

@ KannanKandasamy 10-1-2016の行がその月の一部であるためです。 –

答えて

0

ここで課金期間によってグループにデータをcase文を使用して、あなたはこれを達成できる方法の例です。

DECLARE @myTable TABLE (ContactDate DATE, Zip INT); 
INSERT @myTable VALUES ('10-1-2016', 90210), ('10-7-2016', 90211), ('10-8-2016', 90210), ('10-8-2016', 90211); 

DECLARE @myBilling TABLE (Zip INT, BillingDay INT); 
INSERT @myBilling VALUES (90210, 2), (90211, 2); 

SELECT CAST(CASE WHEN DATEPART(DAY, T.ContactDate) < B.BillingDay 
      THEN DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate) - 1, 0)) 
      ELSE DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate), 0)) 
     END AS DATE) BillingPeriod 
    , T.Zip 
    , COUNT(*) theCount 
FROM @myTable T 
JOIN @myBilling B ON B.Zip = T.Zip 
GROUP BY T.Zip 
     ,CASE WHEN DATEPART(DAY, T.ContactDate) < B.BillingDay 
       THEN DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate) - 1, 0)) 
       ELSE DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate), 0)) 
     END; 
0

あなたは(28〜31日)、月によってグループ化する、またはそれが常にある:それはselect文のあるべき内容を正確に把握するのは難しいですが、一般的な概念はまだここに適用されるようなあなたのテーブルが見て正確に何を知らず30日?

常に30日であれば、これ以外の日付以外の列に加えてグループ化してください。

ceiling(cast(datediff(day,BillingMonthStart,ContactDate) AS FLOAT)/30) 

これにより、BillingMonthStartとContactDateの切り上げまでの30日間の間隔が与えられます。つまり、0日と同じ日に連絡先を数え、30日目を含めます。そして、あなたは、これが代わりに静的30日の月の期間であることにしたい場合は

ceiling((cast(datediff(day,BillingMonthStart,ContactDate) AS FLOAT)+1)/30) 

:あなたは、新しいグループであることを30日目たい場合

datediff(month,@BillingMonthStart,@ContactDate) - CASE 
     WHEN datepart(day,@BillingMonthStart) > datepart(day,@ContactDate) THEN 1 
     ELSE 0 
     END 
+0

私はトップのbtwで自己回答を追加しました。助けてくれてありがとう – Dave