I want to SUM up the last 12 months values from a sql query.
The problem is to sum up the last 12 months, instead of taking just the whole year.
So when I SELECT March 2000 as default in my parameter,
I want the query to SUM up: from March 1999-March 2000.
This is what I got so far:
SELECT Name, SUM(sales) as totalsales, year_month
FROM Total_Sales
WHERE
(year_month = @year_month)
GROUP BY Name, year_month
Thanks for any help!
--EDIT--
SELECT Name, SUM(sales) as totalsales, year_month
FROM Total_Sales
WHERE
(year_month >= @From) AND
(year_month <= @To)
GROUP BY Name, year_month
Added this after suggestions from "Steve Morgan"
Can we add a average for the last 12 months somehow without selecting 12 months in the parameters.
Letting the "@From" parameter decide on start value. Something like: AVG(@From -12 months)??
Thanks again for the help!
--EDIT 2--
The ROW_NUMBER() function is very handy to solve this problem. My query looks like this now:
SELECT Name, SUM(sales)
FROM
(
SELECT rn = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY year, year_month)
, Name
, sales = SUM(sales)
FROM Total_Sales ts
WHERE
(year_month>= @From) AND
(year_month<= @To)
GROUP BY
Name
, year
, year_month
) ts
WHERE
rn <= 12
GROUP BY
Name
This code is longer than Steve Morgans, but is designed to allow the optimiser the ability to use any existing INDEX on the year
and year_month
fields. This is only relevant if you have a relatively large table as it is designed to efficiently know which records can be skipped.
(It also assumes MS SQL Server, but the logic is applicable to other RDBMSes.)
DECLARE
@DateParam AS DATETIME
SELECT
@DateParam = '2011 June 01'
;WITH MyTable (Name, Year, Year_Month, Sales) AS
(
SELECT 'Rod', 2010, 1, 10
UNION ALL SELECT 'Rod', 2010, 2, 10
UNION ALL SELECT 'Rod', 2010, 3, 10
UNION ALL SELECT 'Rod', 2010, 4, 10 UNION ALL SELECT 'Jane', 2010, 4, 10
UNION ALL SELECT 'Rod', 2010, 5, 10 UNION ALL SELECT 'Jane', 2010, 5, 10
UNION ALL SELECT 'Rod', 2010, 6, 10 UNION ALL SELECT 'Jane', 2010, 6, 10
------------------------------------------------------------------------------
UNION ALL SELECT 'Rod', 2010, 7, 10 UNION ALL SELECT 'Jane', 2010, 7, 10
UNION ALL SELECT 'Rod', 2010, 8, 10 UNION ALL SELECT 'Jane', 2010, 8, 10
UNION ALL SELECT 'Rod', 2010, 9, 10 UNION ALL SELECT 'Jane', 2010, 9, 10
UNION ALL SELECT 'Rod', 2010,10, 10 UNION ALL SELECT 'Jane', 2010,10, 10
UNION ALL SELECT 'Jane', 2010,11, 10
UNION ALL SELECT 'Jane', 2010,12, 10
UNION ALL SELECT 'Jane', 2011, 1, 10
UNION ALL SELECT 'Jane', 2011, 2, 10
UNION ALL SELECT 'Rod', 2011, 3, 10 UNION ALL SELECT 'Jane', 2011, 3, 10
UNION ALL SELECT 'Rod', 2011, 4, 10 UNION ALL SELECT 'Jane', 2011, 4, 10
UNION ALL SELECT 'Rod', 2011, 5, 10
UNION ALL SELECT 'Rod', 2011, 6, 10
------------------------------------------------------------------------------
UNION ALL SELECT 'Rod', 2011, 7, 10
)
SELECT
Name,
Year,
Year_Month,
SUM(sales) AS Total_Sales
FROM
MyTable
WHERE
(Year = DATEPART(YEAR, @DateParam) AND Year_Month <= DATEPART(MONTH, @DateParam))
OR (Year = DATEPART(YEAR, @DateParam) - 1 AND Year_Month > DATEPART(MONTH, @DateParam))
GROUP BY
Name,
Year,
Year_Month
Notes:
1. This will give the results for the 12 months up to and including June 2011
2. No data prior to July 2010 will be included
3. The gap for Rod's data won't cause Note 3 to be breached
4. Jane's missing data in May 2011 and June 2011 won't cause Note 3 to be breached
5. The formulation of the WHERE clause will allow INDEXes to be used