I have a dataset that has a product, weeknumber, and sales for that week.
I am trying to find the 4 best consecutive sales weeks in the data, so for example, Product A’s 4 best weeks are 1-4 and Product S’s best weeks are 5-8
I am using SQL to query the table to return the 4 best consecutive weeks & the totals during those weeks (grouping by product)
I am struggling on how to tackle this as I am not an expert in SQL.
So far, I have tried using a lag + subquery to create lags at intervals 1,2,3, & 4. My thought is to do a running total for each new lag column & then find the max value.
I created the lag tables, but something is happening in my ‘over’ statement that is reordering the output for the lags.
I have no idea if this is a good way to tackle the problem, but I have researched and not found anything that can help me for this problem.
select PRODUCT, WEEKNUMBER, LAG_SALES1, LAG_SALES2, SUM(LAG_SALES1) OVER (ORDER BY WEEKNUMBER) AS RUNNING_TOTAL1, SUM(LAG_SALES2) OVER (ORDER BY WEEKNUMBER) AS RUNNING_TOTAL2, SUM(LAG_SALES3) OVER (ORDER BY WEEKNUMBER) AS RUNNING_TOTAL3, FROM( SELECT PRODUCT, WEEKNUMBER, SALES, LAG(SUM(SALES),1) OVER( ORDER BY PRODUCT, WEEKNUMBER) AS LAG_SALES1, LAG(SUM(SALES),2) OVER( ORDER BY PRODUCT, WEEKNUMBER) AS LAG_SALES2, LAG(SUM(SALES),3) OVER( ORDER BY PRODUCT, WEEKNUMBER) AS LAG_SALES3, SUM(SALES) OVER (ORDER BY WEEKNUMBER) AS RUNNING_TOTAL0, from t GROUP BY PRODUCT, WEEKNUMBER, SALES ORDER BY PRODUCT, WEEKNUMBER ) WHERE PRODUCT = 'A' GROUP BY PRODUCT, WEEKNUMBER, LAG_SALES1, LAG_SALES2, LAG_SALES3 ORDER BY PRODUCT, WEEKNUMBER
CREATE TABLE t ( PRODUCT varchar(255), WEEKNUMBER int, SALES int); INSERT INTO t(PRODUCT, WEEKNUMBER, SALES) VALUES ('A',1,17), ('A',2,20), ('A',3,17), ('A',4,10), ('A',5,12), ('A',6,13), ('A',7,2), ('A',8,25), ('S',1,25), ('S',2,20), ('S',3,9), ('S',4,7), ('S',5,24), ('S',6,16), ('S',7,10), ('S',8,24)
Advertisement
Answer
I provide you a sample sql on MySQL. You can use it in other sql languages simply with change CONCAT
function.
SELECT t1.PRODUCT,CONCAT(t1.WEEKNUMBER,",",t2.WEEKNUMBER,",",t3.WEEKNUMBER,",",t4.WEEKNUMBER) as weeks, t1.SALES+t2.SALES+t3.SALES+t4.SALES as sumSale FROM `t` as t1 inner join `t` as t2 inner join `t` as t3 inner join `t` as t4 where t1.PRODUCT = t2.PRODUCT and t1.PRODUCT = t3.PRODUCT and t1.PRODUCT = t4.PRODUCT and t1.WEEKNUMBER = t2.WEEKNUMBER+1 and t1.WEEKNUMBER = t3.WEEKNUMBER+2 and t1.WEEKNUMBER = t4.WEEKNUMBER+3;
Result will be:
And you can find max of sumSale with corresponding weeks.
I provide you the MS SQL sample below which using temp table to do more query:
SELECT t1.PRODUCT, CONCAT(t1.WEEKNUMBER,',',t2.WEEKNUMBER,',',t3.WEEKNUMBER,',',t4.WEEKNUMBER) as weeks, t1.SALES+t2.SALES+t3.SALES+t4.SALES as sumSale into #tempTable FROM t as t1, t as t2, t as t3, t as t4 WHERE t1.PRODUCT = t2.PRODUCT and t1.PRODUCT = t3.PRODUCT and t1.PRODUCT = t4.PRODUCT and t1.WEEKNUMBER = t2.WEEKNUMBER+1 and t1.WEEKNUMBER = t3.WEEKNUMBER+2 and t1.WEEKNUMBER = t4.WEEKNUMBER+3 SELECT PRODUCT,MAX(sumSale) as msale INTO #temp2 FROM #tempTable GROUP BY PRODUCT SELECT tt1.* FROM #tempTable as tt1 INNER JOIN #temp2 as tt2 ON tt1.PRODUCT = tt2.PRODUCT WHERE tt1.sumSale = tt2.msale
In Oracle you can use simply IN clause instead of JOIN for last section.