Reputation: 3
i would really need your help in creating a query where i can show the number of buyers who made more than 1 order in a month for the period January 2017 to December 2017.
Also, the no. of these buyers that didn't order again within the next 12 months.
Below is sample my data.
Date | CID (customer id) | OrderNo |
---|---|---|
2017-02-03 0:23 | 924832 | 000023149 |
2017-02-05 0:11 | 924162 | 000092384 |
2017-07-01 0:53 | 914861 | 000023182 |
2017-08-09 0:42 | 924832 | 000021219 |
Output should be like this
Month | Buyers with >1 order | Buyers that didnt order for the next 12M |
---|---|---|
2017-01-01 | 122 | 92 |
2017-02-01 | 74 | 24 |
2017-03-01 | 216 | 107 |
Upvotes: 0
Views: 170
Reputation: 60462
This should to match your description:
with cte as
(
select
ca.ym
,cid
-- flag buyers who made more than 1 order in a month
,case when count(*) > 1 then 1 else 0 end as multi_buy
-- flag buyers that didn't order again within the next 12 months
,case when LEAD(ym,1,ym) -- month of next order
over (partition by CID
order by ym) < DATEADD(month, 13, ym)
then 0
else 1
end as no_buy_within_range
from orders
CROSS APPLY
( -- truncate the OrderDate to the 1st of month
SELECT convert(Date, DATEADD(month, DATEDIFF(month, 0, OrderDate), 0)) as ym
) as ca
group by
ym
,cid
)
select
ym
,sum(multi_buy)
,sum(no_buy_within_range)
from cte
group by ym
order by ym
Upvotes: 1
Reputation: 1751
I made this setup here http://sqlfiddle.com/#!18/090ac/5
;WITH CTE AS
(
select CAST(DATEADD(month, DATEDIFF(month, 0, OrderDate), 0) as DATE) AS OrderMonth,
CID,count(OrderNo) as OrderCount
from Orders
group by CAST(DATEADD(month, DATEDIFF(month, 0, OrderDate), 0) as DATE), CID
)
select q1.OrderMonth, q1.[MultipleOrderBuyers], q2.OrderedOverNext12Mo
from
(
select OrderMonth,
SUM(CASE WHEN OrderCount > 1 THEN 1 ELSE 0 END) as [MultipleOrderBuyers]
from CTE
group by OrderMonth
)q1
LEFT OUTER JOIN
(
select OrderMonth, SUM(OrderedOverNext12Mo) as OrderedOverNext12Mo
from
(
select OrderMonth, CID,
( select CASE WHEN SUM(OrderCount) > 1 THEN 1 ELSE 0 END
from CTE
where OrderMonth BETWEEN DATEADD(month,1,c1.OrderMonth) AND DATEADD(month,13,c1.OrderMonth)
) as OrderedOverNext12Mo
from CTE c1
group by OrderMonth, CID
)c
group by OrderMonth
)q2 on (q1.OrderMonth = q2.OrderMonth)
Upvotes: 0
Reputation: 1
If I understood correctly, the table with sample data is the table of Orders, which means that one row is one order with unique OrderNo.
If so, then the following query would have to work:
SELECT d.[MONTH], COUNT(distinct d.[Buyers with >1 order]) [Buyers with >1 order],
COUNT(distinct d.[Buyers that didnt order for the next 12M]) [Buyers that didnt order for the next 12M]
FROM
(
select c.[MONTH], c.[Date], c.CID, c.OrderNo,
c.[Buyers with >1 order],
case when c.[Buyers with >1 order] is not null and
datediff(MONTH, c.[Date], LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])) > 12
THEN C.CID END [Buyers that didnt order for the next 12M]
from (
SELECT b.[MONTH], b.[Date], b.CID, b.OrderNo,
case when COUNT(*) over (partition by b.[MONTH], b.CID) > 1 then b.CID end [Buyers with >1 order]
FROM (
SELECT convert(date, DATEADD(month, DATEDIFF(month, 0, a.Date), 0)) [MONTH],
A.[Date], A.CID, A.OrderNo
FROM Orders a
) b
) c
) d
WHERE D.[MONTH] BETWEEN '2017-01-01' AND '2017-12-01'
GROUP BY d.[MONTH]
UPD: I just noted your comment clarifying the meaning of "Buyers that didn't order for the next 12M": "if you ordered last January 2017, you shouldnt have any orders from Feb 2017 to Feb 2018"
For such cases, the part of the query
datediff(MONTH, c.[Date], LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])) > 12
ought to be altered to
DATEADD(DAY,1,EOMONTH(DATEADD(MONTH,13,C.[DATE]))) <= LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])
Then the full query would look like:
SELECT d.[MONTH], COUNT(distinct d.[Buyers with >1 order]) [Buyers with >1 order],
COUNT(distinct d.[Buyers that didnt order for the next 12M]) [Buyers that didnt order for the next 12M]
FROM
(
select c.[MONTH], c.[Date], c.CID, c.OrderNo,
c.[Buyers with >1 order],
case when c.[Buyers with >1 order] is not null and
datediff(MONTH, c.[Date], LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])) > 12
THEN C.CID END [Buyers that didnt order for the next 12M]
from (
SELECT b.[MONTH], b.[Date], b.CID, b.OrderNo,
case when COUNT(*) over (partition by b.[MONTH], b.CID) > 1 then b.CID end [Buyers with >1 order]
FROM (
SELECT convert(date, DATEADD(month, DATEDIFF(month, 0, a.Date), 0)) [MONTH],
A.[Date], A.CID, A.OrderNo
FROM Orders a
) b
) c
) d
WHERE D.[MONTH] BETWEEN '2017-01-01' AND '2017-12-01'
GROUP BY d.[MONTH]
Upvotes: 0