Home > database >  TSQL - Query to get sum of last 3 months QTY
TSQL - Query to get sum of last 3 months QTY

Time:06-14

I am working on a query to get sum of (current last 2 month) QTY based on a date field in the table.

CREATE table #temp_Sales
( Client varchar(10),
Sale_Month Date,
Qty int)

Insert into #temp_Sales VALUES
  ( 'AAAA', '2022-06-01',  5 ),
  ( 'AAAA', '2022-05-01',  10 ),
  ( 'AAAA', '2022-05-01',  2 ),
  ( 'AAAA', '2022-04-01',  5 ),
  ( 'AAAA', '2022-02-01',  15),
  ( 'BBBB', '2022-05-01',  2 ),
  ( 'BBBB', '2022-04-01',  4),
  ( 'BBBB', '2022-03-01', 6 ),
  ( 'BBBB', '2022-03-01', 10 ),
  ( 'BBBB', '2022-01-01', 6 ),
  ( 'BBBB', '2021-10-01', 10),
  ( 'BBBB', '2021-09-01', 2 ),
  ( 'BBBB', '2021-11-01', 4 ),
  ( 'BBBB', '2021-08-01', 6),
  ( 'BBBB', '2021-07-01',  8 ),
  ( 'CCCC', '2021-11-01', 2 ),
  ( 'CCCC', '2021-10-01', 3 ),
  ( 'CCCC', '2021-09-01', 30 ),
  ( 'CCCC', '2021-06-01', 4 )

Sample data:

enter image description here

Expected Output:

enter image description here

The Sale_month is not consecutive and same month can appear more than once for a client in the table.

Example : For the Client AAAA and Sale Month 2022-06-01 the qty should include the sum(QTY) of current and last 2 months ( 2022-06-01,2022-05-01 and 2022-04-01) for that client. QTY = 5 10 2 5 = 22

For the client BBBB and Sale month 2022-03-01 . QTY = 6 10 6 = 22

  ;With da AS
  (SELECT *, DATEADD(MM,-2,Sale_month)as last_two_Months FROM #temp_Sales)

  Select Client,Sale_month,Sum(qty) from da
  WHERE Sale_month Between last_two_Months and Sale_month
  GROUP BY Client,Sale_month
  Order by client

Tried the above query. But not working as expected not sure how to group by using last_two_Months and Sale_month. Any help is much appreciated.

CodePudding user response:

Here is one way you could tackle this.

select Sale_Month
    , client
    , Last3Months = max(x.PeriodSales)
from #temp_Sales s
cross apply
(
    select PeriodSales = sum(Qty)
    from #temp_Sales s2
    where s2.Sale_Month >=  dateadd(month, -2, s.Sale_Month)
        and s2.Sale_Month <= s.Sale_Month
        and s2.Client = s.Client
) x
group by Sale_Month
    , client
order by Client
    , Sale_Month desc

CodePudding user response:

group on qty to eliminate duplicates, then join to self like this:

;WITH CTE AS(
    select
        [Client],
        [Sale_Month],
        SUM(QTY) QTY
    from #tmp
    group by 
        [Client],
        [Sale_Month]
)
select a.[Client], a.[Sale_Month], SUM(b.QTY) QTY
from 
CTE a
INNER JOIN CTE b on 
    a.Client = b.Client and 
    DATEDIFF(mm, b.[Sale_Month], a.[Sale_Month]) between 0 and 3
group by 
    a.[Client], a.[Sale_Month]

CodePudding user response:

Firstly, if you don't already have a Calendar Table invest in one.

After that, you can create the data set you need by JOINing data from your Sales table to your calendar table, then getting the sales via a LEFT JOIN and aggregating them. Then you can use a windowed SUM for the last 3 months. Finally, as you seem to not want months that don't exist, filter those back out:

WITH Clients AS(
    SELECT Client,
           MIN(Sale_Month) AS MinMonth,
           MAX(Sale_Month) AS MaxMonth
    FROM dbo.Sales
    GROUP BY Client),
ClientDates AS(
    SELECT C.Client,
           CT.CalendarDate
    FROM Clients C
         JOIN dbo.CalendarTable CT ON C.MinMonth <= CT.CalendarDate
                                  AND C.MaxMonth >= CT.CalendarDate
    WHERE CT.CalenderDay = 1),
ClientSales AS(
    SELECT CD.Client,
           CD.CalendarDate,
           SUM(S.Qty) AS Qty
    FROM ClientDates CD
         LEFT JOIN dbo.Sales S ON CD.Client = S.Client
                              AND CD.CalendarDate = S.Sale_Month
    GROUP BY CD.Client,
             CD.CalendarDate),
Last3 AS(
    SELECT CS.Client,
           CS.CalendarDate,
           CS.Qty,
           SUM(CS.Qty) OVER (PARTITION BY CS.Client ORDER BY CS.CalendarDate
                             ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS Last3Months
    FROM ClientSales CS)
SELECT L3.Client,
       L3.CalendarDate AS Sale_Month,
       L3.Last3Months
FROM Last3 L3
WHERE L3.Qty IS NOT NULL
ORDER BY Client,
         Sale_Month DESC;
  • Related