Reputation: 37
Let's say I have data like this
CustomerID | Trans_date |
---|---|
C001 | 01-sep-22 |
C001 | 04-sep-22 |
C001 | 14-sep-22 |
C002 | 03-sep-22 |
C002 | 01-sep-22 |
C002 | 18-sep-22 |
C002 | 20-sep-22 |
C003 | 02-sep-22 |
C003 | 28-sep-22 |
C004 | 08-sep-22 |
C004 | 18-sep-22 |
But I'm unable to find the first and second transaction based on Trans_date. I wish for the result to look like this:
CustomerID | Trans_week | first | second |
---|---|---|---|
C001 | 35 | 35 | 37 |
C001 | 35 | 35 | 37 |
C001 | 37 | 35 | 37 |
C002 | 35 | 35 | 37 |
C002 | 35 | 35 | 37 |
C002 | 37 | 35 | 37 |
C002 | 38 | 35 | 37 |
C003 | 35 | 35 | 39 |
C003 | 39 | 35 | 39 |
C004 | 36 | 36 | 37 |
C004 | 37 | 36 | 37 |
And for the last result will show like this:
CustomerID | first | second |
---|---|---|
C001 | 35 | 37 |
C002 | 35 | 37 |
C003 | 35 | 39 |
C004 didnt include because i would need who cust id who come first in their 1st week.
Upvotes: 1
Views: 110
Reputation: 313
with cte (RN,CustomerID, FirstWeek,SecondWeek ) as
( SELECT ROW_NUMBER() over(partition by CustomerID ORDER BY CustomerID ) RN, CustomerID,FirstWeek, isnull((select TOP 1 (DATEPART(week,CustTrans))
from trydata c
where c.CustomerID = SRC.CustomerID AND DATEPART(week,C.CustTrans) > SRC.FirstWeek
ORDER BY DATEPART(week,C.CustTrans) ),'0') AS SecondWeek
FROM (
SELECT CustomerID,DATEPART(week,CustTrans) TransWeek,
(select MIN(DATEPART(week,CustTrans)) from trydata c where c.CustomerID = trydata.CustomerID) AS FirstWeek
FROM trydata
) SRC )
select CustomerID,FirstWeek,SecondWeek from cte where RN = 1
Output:
Example 2 :
WITH CTE (CustomerID,FIrstWeek,RN) AS (
SELECT CustomerID,MIN(DATEPART(week,CustTrans)) TransWeek,
ROW_NUMBER() over(partition by CustomerID ORDER BY DATEPART(week,CustTrans) asc ) FROM TryData
GROUP BY CustomerID,DATEPART(week,CustTrans)
)
SELECT CTE.CustomerID, CTE.FIrstWeek,
(select TOP 1 (DATEPART(week,c.CustTrans))
from trydata c
where c.CustomerID = CTE.CustomerID AND DATEPART(week,C.CustTrans) > CTE.FIrstWeek
) SecondWeek
FROM CTE
WHERE RN = 1
Edit: This can be done on easier way and less complex.
Upvotes: 1
Reputation: 9191
You may use ROW_NUMBER()
function -inside a subquery- to get the first and second transaction dates for a customer, then use conditional MAX
window function on the results of that subquery.
SELECT CustomerID, DATEPART(week,CustTrans) AS Trans_week,
DATEPART(week, MAX(CASE rn WHEN 1 THEN CustTrans END) OVER (PARTITION BY CustomerID)) first,
DATEPART(week, MAX(CASE rn WHEN 2 THEN CustTrans END) OVER (PARTITION BY CustomerID)) second
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY CustTrans) rn
FROM trydata
) T
ORDER BY CustomerID, Trans_week
See a demo on SQL Server.
As you requested in the comments, if you want to select only one row per customer that showing the first and second weeks, use the following query:
SELECT CustomerID,
DATEPART(week, MAX(CASE rn WHEN 1 THEN CustTrans END)) first,
DATEPART(week, MAX(CASE rn WHEN 2 THEN CustTrans END)) second
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY CustTrans) rn
FROM trydata
) T
WHERE rn <= 2
GROUP BY CustomerID
ORDER BY CustomerID
See a demo.
Upvotes: 1