I've customers transaction data of around 20 million records for a month. For a campaign I need to get customers' qualification for reward on following patterns:
- Customer will qualify for each transaction he would perform after 7 days.
- Any transaction performed within 7 days window will be ignored
For Example: 1) If User-A has done transaction on 3rd, 4th, 6th, 7th, 9th, 11th, 28th - he will be rewarded for 3rd, 9th & 28th dated transactions and all transactions in between will be ignored. 2) If User-B has done transaction on 1st, 4th, 11th, 17th, 21st, 30th - he will be rewarded for 1st, 11th, 17th & 30th dated transactions and all transactions in between will be ignored. 3) if User-C has done transaction on 1st and 30th - he will be rewarded for both transactions.
I've spent 3 days and tried to do it many ways, but due to my limited knowledge I could not succeeded.
I've tried to do it through loop query which was giving required results but processing 20 million records through loop is taking hell of time.
Please help me with any efficient solution to get this done. I'll be really really grateful for this.
Following is simple query statement which is just good for nothing but I've tried:
SELECT t1.[FINANCIAL ID],
t1.MSISDN,
t1.[DATE],
MIN(t2.[DATE]) AS [NEXT DATE],
ISNULL(DATEDIFF(DAY, t1.[DATE], MIN(t2.[DATE])), 0) AS DAYSDIFF1
FROM mydb.dbo.RequiredTrxnForCampaign t1
LEFT JOIN mydb.dbo.RequiredTrxnForCampaign t2
ON t1.MSISDN = t2.MSISDN
AND t2.[DATE] > t1.[DATE]
GROUP BY t1.[FINANCIAL ID], t1.MSISDN, t1.[DATE]
Following is Loop query I've tried but it is taking 40 minutes for 100K records with all possible optimizations I could have done.
DECLARE @minid int = (SELECT MIN(rownumber) FROM mydb.dbo.Test_5k t)
DECLARE @maxid int = (SELECT MAX(rownumber) FROM mydb.dbo.Test_5k t)
DECLARE @fid varchar(11) = NULL
DECLARE @msisdn varchar(20) = NULL
DECLARE @date datetime = NULL
DECLARE @product varchar(50) = NULL
DECLARE @checkmsisdn smallint = NULL
DECLARE @checkdate datetime = NULL
DECLARE @datediff int = NULL
TRUNCATE TABLE mydb.dbo.MinDateTable
TRUNCATE TABLE mydb.dbo.Test_5k_Result
WHILE (@minid <= @maxid)
BEGIN
SET @fid = (SELECT tk.[FINANCIAL ID] FROM dbo.Test_5k tk WHERE tk.rownumber = @minid)
SET @msisdn = (SELECT tk.MSISDN FROM dbo.Test_5k tk WHERE tk.rownumber = @minid)
SET @date = (SELECT tk.[DATE] FROM dbo.Test_5k tk WHERE tk.rownumber = @minid)
SET @product = (SELECT tk.[PRODUCT NAME] FROM dbo.Test_5k tk WHERE tk.rownumber = @minid)
SET @checkmsisdn = (SELECT count(*) FROM dbo.MinDateTable mdt WHERE mdt.MSISDN=@msisdn)
SET @checkdate = (SELECT mdt.[MIN DATE] FROM dbo.MinDateTable mdt WHERE mdt.MSISDN=@msisdn)
SET @datediff = (ISNULL(DATEDIFF(DAY, @checkdate, @date), 0))
IF (@checkmsisdn = 0)
BEGIN
INSERT INTO dbo.MinDateTable (MSISDN, [MIN DATE])
VALUES (@msisdn, @date);
INSERT INTO dbo.Test_5k_Result (MSISDN, [DATE], [PRODUCT NAME], [FINANCIAL ID], DAYSDIFF)
VALUES (@msisdn, @date, @product, @fid, @datediff);
END
ELSE
BEGIN
IF (@checkmsisdn > 0 AND @datediff >= 6)
BEGIN
UPDATE dbo.MinDateTable
SET [MIN DATE] = @date
WHERE MSISDN=@msisdn
INSERT INTO dbo.Test_5k_Result (MSISDN, [DATE], [PRODUCT NAME], [FINANCIAL ID], DAYSDIFF)
VALUES (@msisdn, @date, @product, @fid, @datediff);
END
END
SET @minid = @minid + 1
END;
Required result are to get all those transactions out of 20 million where customer will be rewarded as per above details.