2014-09-23 39 views
1

我正在努力解決使用公式來識別忠誠客戶的問題,我希望獲得一些見解。 的忠實客戶標準如下:SQL Server連續發票不包括36個月後的差距

  • 客戶必須已經開發票至少4次36 個月內,與發票落在下列時間範圍:
    • 第一發票(A) - 這並不一定要在第一時間將 客戶的要求不斷開發票,只是第一張發票落入 這種模式
    • 第二張發票(B) - 有發票後一
    • 從1-12個月 發生3210
    • 第三發票(C) - 具有發票甲
    • 第四發票(d)之後,從13-24個月 發生 - 已經從25-36個月 發生發票A之後
  • 一旦這些標準得到滿足,所有發票與日期比 或等於A更大的被認爲是忠實客戶發票
    • 只有具有正子總數發票應該算作排位 發票(A,B,C,或d),但所有發票應計入一次 客戶符合資格特里亞

到目前爲止,我與這個確定。下面是我使用(這是相當緩慢的,但我沒有運行很頻繁,所以我沒有特別關注速度)查詢:

;WITH 

T1 AS 
( 
SELECT 
CUSTOMER_ID, 
INVOICE_DATE, 
DATEPART(YEAR, INVOICE_DATE)*12 + DATEPART(MONTH, INVOICE_DATE) AS YM 
FROM INVOICE 
WHERE Sub_Total > 0 
), 

T2 AS 
(
SELECT DISTINCT 
A.CUSTOMER_ID, 
A.INVOICE_DATE A_DATE 
FROM T1 A 
JOIN T1 B ON A.CUSTOMER_ID = B.CUSTOMER_ID AND (B.YM > A.YM AND B.YM <= (A.YM + 12)) 
JOIN T1 C ON A.CUSTOMER_ID = C.CUSTOMER_ID AND (C.YM > B.YM AND C.YM BETWEEN (A.YM + 13) AND (A.YM + 24)) 
JOIN T1 D ON A.CUSTOMER_ID = D.CUSTOMER_ID AND (D.YM > C.YM AND D.YM BETWEEN (A.YM + 25) AND (A.YM + 36)) 
) 

SELECT DISTINCT 
I.CUSTOMER_ID, 
C.CUSTOMER_NAME, 
I.INVOICE_ID, 
cast(i.Invoice_Date as Date) as Invoice_Date, 
DATEPART(YEAR, I.INVOICE_DATE)*12 + DATEPART(MONTH, I.INVOICE_DATE) AS YM, 
DATEPART(MONTH, I.INVOICE_DATE) AS Mo, 
DATEPART(YEAR, I.INVOICE_DATE) AS Yr, 
I.SUB_TOTAL 
FROM INVOICE I 
JOIN T2 ON T2.CUSTOMER_ID = I.CUSTOMER_ID AND I.INVOICE_DATE >= A_DATE 
JOIN CUSTOMER C ON C.CUSTOMER_ID = I.CUSTOMER_ID 
ORDER BY I.CUSTOMER_ID, INVOICE_DATE 

然而,是什麼導致我被卡住是另一個標準指出,如果一位忠誠顧客在未開具發票的情況下長達36個月,他們就不再被視爲忠誠顧客,36個月之後的任何發票都不應計入在內。如果客戶在36個月的差額後再次完成上述(A,B,C和D)4項合格發票,則被視爲一套新的忠誠發票。

例子:

 
+--------------------+--------------------+-----------------+ 
| Invoice Month/Year | Qualifying Invoice | Count as Loyal? | 
+--------------------+--------------------+-----------------+ 
| 01/04    | N/A    | No    | 
| 03/05    | A     | Yes    | 
| 09/05    | B     | Yes    | 
| 12/05    | N/A    | Yes    | 
| 06/06    | C     | Yes    | 
| 04/07    | D     | Yes    | 
| 06/07    | N/A    | Yes    | 
| 07/10    | N/A    | No    | 
| 08/10    | N/A    | No    | 
| 09/11    | A     | Yes    | 
| 10/11    | B     | Yes    | 
| 01/13    | C     | Yes    | 
| 04/14    | D     | Yes    | 
| 06/14    | N/A    | Yes    | 
+--------------------+--------------------+-----------------+ 

我道歉,如果我做這個太複雜。最終,我希望瞭解如何在36個月的差距後排除所有發票,但那些再次符合忠誠客戶標準的發票除外。

+0

複雜,因爲這是,你可以考慮[製作小提琴(http://sqlfiddle.com),這樣很容易看到的數據。 – paqogomez 2014-09-23 20:35:26

+0

也許是另一個CTE,包含緊接着36個月乾旱的發票,並自動將那些忠誠的旗幟設置爲否? – 2014-09-23 21:07:31

回答

1

這是一種使用CTE計算間隙的方法。如果你有SQL2012或更高版本,那麼lag窗口函數使得這個更簡單。

祝你好運併入信息!

with x as (
    select 
    invoice_id, 
    customer_id, 
    invoice_date, 
    row_number() over (partition by customer_id order by invoice_date) rn 
    -- SQL2012 has lag which is easier, can compute the gap directly (untested) 
    -- datediff(month, lag(invoice_date, 1) over (
    --  partition by customer_id 
    --  order by invoice_date 
    --), invoice_date) as gap 
    from 
    invoice 
    where 
    sub_total > 0 
) select 
    x1.*, 
    datediff(month, x2.invoice_date, x1.invoice_date) gap 
from 
    x x1 
    left join 
    x x2 
    on x1.customer_id = x2.customer_id and x1.rn = x2.rn + 1; 

Example SQLFiddle