1

I have a column Amount which I want to get its sum by month within each year.

I have tried the following query and it works well for year but month is summing up incorrectly. For instance in this May, it's summing up all the month of May in various years. So I want it to sum each current month at a time.

DECLARE @currentYear int
DECLARE @currentMonth int

SELECT @currentYear = DATEPART(year, GETDATE())
SELECT @currentMonth = DATEPART(month, GETDATE())

SELECT
  SUM(
    CASE
      WHEN DATEPART(month,[Date]) = @currentMonth THEN Amount
      ELSE 0
    END
  ) AS 'This Month',
  SUM(
    CASE
      WHEN DATEPART(year,[Date]) = @currentYear THEN Amount
      ELSE 0
    END
  ) AS 'This Year'
FROM Orders
3
  • You need AND --> WHEN DATEPART(month,[Date]) = @currentMonth AND DATEPART(year,[Date]) = @currentYear
    – topsail
    Commented May 15, 2023 at 21:14
  • Why can you not simply aggregate and filter with where [date] > start and [date] <= end, it would be far more performant than scanning all rows.
    – Stu
    Commented May 15, 2023 at 21:16
  • Are you seriously still using SQL Server 2005? Long past time to upgrade.
    – Dale K
    Commented May 16, 2023 at 1:25

3 Answers 3

1
SQL SERVER 2012+

This should get you the two sums you need, with a where clause added to never include any amounts outside of the current year:

DECLARE @currentYear INT;
DECLARE @currentMonth INT;

SELECT @currentYear = DATEPART(YEAR, GETDATE());
SELECT @currentMonth = DATEPART(MONTH, GETDATE());

SELECT 
    SUM(CASE WHEN DATEPART(MONTH, [Date]) = @currentMonth THEN Amount ELSE 0 END) AS [This Month],
    SUM(Amount) AS [This Year]
FROM Orders
WHERE 
    [Date] >= DATETIMEFROMPARTS(YEAR(GETDATE()), 1, 1, 0, 0, 0, 0) 
    AND [Date] < DATETIMEFROMPARTS(YEAR(GETDATE()) + 1, 1, 1, 0, 0, 0, 0);
Sql Server 2005/2008

It looks like we don't have DateTimeFromParts yet so here's an alternative:

DECLARE @currentYear INT;
DECLARE @currentMonth INT;
DECLARE @YearStart DATETIME;
DECLARE @YearEndExclusive DATETIME;

SELECT @currentYear = DATEPART(YEAR, GETDATE());
SELECT @currentMonth = DATEPART(MONTH, GETDATE());

SELECT @YearStart = CAST(CAST(@currentYear AS VARCHAR(4)) + '0101' AS DATETIME);
SELECT @YearEndExclusive = CAST(CAST(@currentYear + 1 AS VARCHAR(4)) + '0101'  AS DATETIME);

SELECT 
    SUM(CASE WHEN DATEPART(MONTH, [Date]) = @currentMonth THEN Amount ELSE 0 END) AS [This Month],
    SUM(Amount) AS [This Year]
FROM Orders
WHERE 
    [Date] >= @YearStart 
    AND [Date] < @YearEndExclusive;
1
  • 2
    I'm pretty sure DATETIMEFROMPARTS was added in 2012; the OP indicates they are using 2005 (which has been unsupported for around 7 years).
    – Thom A
    Commented May 16, 2023 at 0:00
0

This won't work for SQL Server 2005, but it will work on SQL Server 2022+. You can use DATETRUNC() to get a date truncated to different time offsets (quarter, month, day, etc.).

SELECT SUM(Amount), DATETRUNC(Date, mm) AS date_truncated
FROM ORDERS
GROUP BY DATETRUNC(Date, mm)

Documentation for DATETRUNC

-1

Your query returns the total for the current month for all years.

Add a condition on year to the WHERE clause, which then simplifies the year total to just SUM(Amount():

SELECT
  SUM(CASE WHEN DATEPART(month,[Date]) = @currentMonth THEN Amount END) AS 'This Month',
  SUM(Amount) AS 'This Year'
FROM Orders
WHERE DATEPART(year,[Date]) = @currentYear

Also, note that you don't need the ELSE in the CASE, because SUM() ignores nulls (which are returned when no CASE matches).

Not the answer you're looking for? Browse other questions tagged or ask your own question.