简体   繁体   中英

Calculate Average of each month in SQL Server

I'm having two tables

Promo

ID | Name
---+---------    
1    Front
2    Middle
3    Back

PromoRate

ID |    Date    | Rate | PromoID
---+------------+------+----------
1    2020-01-01   100       1
2    2020-01-02   200       1
3    2020-02-03   300       1
4    2020-02-01   150       2
5    2020-01-02   250       2
6    2020-03-03   350       2
7    2020-03-01   200       3
8    2020-01-02   400       3
9    2020-01-03   600       3

I want to calculate average. Something like this

Name   | Avg(Jan) | Avg(Feb) | Avg(Mar)
-------+----------+----------+----------
Front      150        300        NULL
Middle     250        150        350
Back       500        NULL       200

Like pivot or something.

Please help me. Thanks in advance

What I've tried:

SELECT * FROM
(
    SELECT P.ID, P.Name, AVG(Rate) AS 'AVG' FROM PromoRate PR
    INNER JOIN Promo P ON P.ID = PR.ProfileID
    WHERE MONTH(Date) = MONTH(GETDATE())
    GROUP BY P.Name, P.ID
) M1
LEFT JOIN
(
    SELECT P.ID, P.Name, AVG(Rate) AS 'AVG' FROM PromoRate PR
    INNER JOIN Promo P ON P.ID = PR.ProfileID
    WHERE MONTH(Date) = MONTH(GETDATE()) + 1
    GROUP BY P.Name, P.ID
) M2 ON M1.ID = M2.ID
LEFT JOIN
(
    SELECT P.ID, P.Name, AVG(Rate) AS 'AVG' FROM PromoRate PR
    INNER JOIN Promo P ON P.ID = PR.ProfileID
    WHERE MONTH(Date) = MONTH(GETDATE()) + 2
    GROUP BY P.Name, P.ID
) M3 ON M2.ID = M3.ID

But it's not working as expected

You need to group on Month(Date), I'd also use DateAdd rather than month(GetDate()) + 2. You can then use the one query rather than joining on 3 queries as you're going to run into trouble when you cross the year line, or if you have multiple years. Eg running it in November will also return the results for January that year and next year.

If this is part of a stored procedure I'd also recommend creating an @startdate and @enddate variable and setting those up first.

declare @start datetime
    declare @end datetime

    select @start = convert(date,GETDATE()), @end = convert(date, DATEADD(month, 2, GETDATE()))

SELECT P.ID, P.Name, AVG(Rate) AS 'AVG' FROM PromoRate PR
    INNER JOIN Promo P ON P.ID = PR.ProfileID
    WHERE Convert(date, Date) > @start and convert(date, date) < @end
    GROUP BY P.Name, P.ID, MONTH(Date)

ETA: You also need to return your month so that you can populate your pivot table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM