我正在努力解决使用公式来识别忠诚客户的问题,我希望能够提供一些见解。 忠诚客户标准如下:
到目前为止,我对此很满意。这是我正在使用的查询(这很慢,但我不是经常运行它所以我并不特别关心速度):
;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 :(得分: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;