How can l group row data by date using window function?

  • Hi

    In my code below the row data are not grouping into month by month name. I want to group row data of the same month.

    |   Date            | Revenue |

    | -------------- |---------|

    | 2023-03-01 |   500   |

    | 2023-03-29 |   300   |

    | 2023-04-15  |   600   |

    | 2023-05-11  |   300   |

    | 2023-05-23 |   600   |

    | 2023-05-31 |   500   |

     

    `

    SELECT

    DATENAME(month, OrderDate) as Month,

    Sum(Amount) as revenue,

    Amount - LAG (Amount) OVER (ORDER BY OrderDate ASC) AS Revenue_growth

    FROM OrderDetail

    Group by OrderDate

    `

    Expected output

    |   Date     | Revenue | Revenue_growth |

    | ---------- | --------- | ------------------- |

    |    March   |   800    |        0                |

    |    April    |   600     |     -200             |

    |    May     |   1400   |      800             |

     

  • You have to sum first, and then use LAG on that result to get what you want... like this... Oh, and since you're new, I created tables for you etc. You should do that from now on... makes answering your questions much easier!

    use tempdb;
    go

    CREATE TABLE Revenues (
    RevenueDate DATE,
    Amount INT
    );
    GO
    INSERT INTO Revenues VALUES
    ('2023-03-01' , 500 ),
    ('2023-03-29' , 300 ),
    ('2023-04-15' , 600 ),
    ('2023-05-11' , 300 ),
    ('2023-05-23' , 600 ),
    ('2023-05-31' , 500 );

    SELECT d.FOM
    , d.Month_name
    , d.Amount
    , PrevAmt = LAG(d.Amount,1) OVER (ORDER BY d.FOM)
    , RevenueGrowth = d.Amount - LAG(d.Amount,1) OVER (ORDER BY d.FOM)
    FROM
    (SELECT FOM = DATEFROMPARTS(YEAR(RevenueDate),MONTH(RevenueDate),1)
    , Month_Name = FORMAT(RevenueDate,'MMMM')
    , Amount
    FROM Revenues) d;
  • It's because you're using the wrong GROUP BY expression.  You're grouping on DATE, not by MONTH.  You need to use an expression that gives you the same value for every date within a given month.  I like EOMONTH(), but Piet's expression will also work.

    You also do not need to sum first and then do a lag.  You can do it all in one fell swoop.

    Note, you cannot use OrderDate directly.  You either need to use the chose unique expression or an aggregate on any other expression that uses OrderDate.

    Also, you are missing aggregates on your expressions for the Revenue growth calculation.  You may also want to specify a default value for the LAG by specifying the optional 2nd and 3rd parameters.

    SELECT
    MIN(DATENAME(month, OrderDate)) as Month,
    Sum(Amount) as revenue,
    SUM(Amount) - LAG (SUM(Amount)) OVER (ORDER BY EOMONTH(OrderDate) ASC) AS Revenue_growth
    FROM OrderDetail
    Group by OrderDate

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • Thank you all

  • Merry_U wrote:

    Thank you all

    I was exploring the question/solutions and noticed that neither of the queries grouped the March or May records into one monthly total, so they return mutliple records per month name.

    I broke it up into two parts for my clarity. My first CTE uses Drew's idea with EOMONTH() to aggregate monthly amounts. Next, I used pietlinden's lag to calculate monthly revenue growth. In my lag, I added a default so the first record would return a zero for revenue growth (essentially just a End_Of_Month_Amount - End_Of_Month_Amount = 800 - 800 = 0) since the first record lag would return a null. You could also wrap the calculation in an isnull or other code to handle the null.

    If you use Drew's query and group by EOMONTH(OrderDate) instead of just OrderDate, it produces desired results with the exception of the first record's zero revenue growth.

    with cte_Monthly_Aggregates as (
    SELECT
    EOMONTH(OrderDate) as End_Of_Month_Date,
    Sum(Amount) as End_Of_Month_Amount
    FROM #OrderDetail
    Group by EOMONTH(OrderDate)
    )
    select
    End_Of_Month_Date,
    DATENAME(month, End_Of_Month_Date) as Month_Name,
    End_Of_Month_Amount,
    End_Of_Month_Amount - LAG (End_Of_Month_Amount, 1, End_Of_Month_Amount) OVER (ORDER BY End_Of_Month_Date ASC) AS Revenue_growth
    FROM cte_Monthly_Aggregates

Viewing 5 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic. Login to reply