I have a table that has NAMES
, DATES
and PRICE
columns. I'm running a query against that table to have a summary based on Name and show 2 totals. The values in PRICE
are positive and negative.
I currently have 2 columns in the query CurTotal
and CurPay
that select and sum price based different date ranges into those columns. I am looking to make it so only the positive values within the date ranges in the PRICE
column can are summed into column CerPay. I think I am close with a case expression, but I can't get it to work out see the code shown below.
Here is what I have that works but it sums all values and puts them in CURPAY
:
SELECT
Tracking.Name,
SUM(IIF(tracking.Date BETWEEN DateSerial(YEAR(DATE()), 1, 1)
AND DateSerial(YEAR(DATE()), 12, 31), Tracking.Price, 0)) AS CurTotal,
SUM(IIF(tracking.Date BETWEEN DateSerial(YEAR(DATE()), 1, 1)
AND DateSerial(YEAR(DATE()), MONTH(DATE()) - 1, 31), tracking.price, 0)) AS PreMonth,
SUM(IIF(tracking.Date BETWEEN DateSerial(YEAR(DATE()), 1, 1)
AND DateSerial(YEAR(DATE()), MONTH(DATE()) - 1, 31), tracking.price, 0)) AS Curpay
FROM
Tracking
WHERE
(((Tracking.Date) BETWEEN DateSerial(YEAR(DATE()), 1, 1)
AND DateSerial(YEAR(DATE()), 12, 31)))
GROUP BY
Tracking.Name
ORDER BY
Tracking.Name;
Here is what I got to with wanting it to sum only the positive values into CURPAY
but it keeps failing:
SELECT Tracking.Name,
Sum(IIf(tracking.Date Between DateSerial(Year(Date()),1,1)
And DateSerial(Year(Date()),12,31),Tracking.Price,0)) AS CurTotal,
Sum(IIf(tracking.Date Between DateSerial(Year(Date()),1,1)
And DateSerial(Year(Date()),Month(Date())-1,31),tracking.price,0)) AS PreMonth,
Sum(CASE WHEN IIf(tracking.Date Between DateSerial(Year(Date()),1,1)
And DateSerial(Year(Date()),Month(Date())-1,31), tracking.price ,0 )> 0, THEN
IIf(tracking.Date Between DateSerial(Year(Date()),1,1) And DateSerial(Year(Date()),Month(Date())-1,31), tracking.price ,0)
ELSE 0
END)AS Curpay
FROM Tracking
WHERE (((Tracking.Date) Between DateSerial(Year(Date()),1,1) And DateSerial(Year(Date()),12,31)))
GROUP BY Tracking.Name
ORDER BY Tracking.Name;
To sum positive prices, use expression
IIF(tracking.price>0,tracking.price,0.0)
This is equivalent of expression
CASE WHEN tracking.price>0 THEN tracking.price ELSE 0.0 END
Safely calculate end of current month as begin of next month -1 day:
(DateSerial(Year(Date()),Month(Date())+1,1)-1)
This works also for december. Test (DateSerial(Year(Dateserial(2025,12,31)),Month(Dateserial(2025,12,31))+1,1)-1)=31.12.2025
end of previous month
as first day of current month -1 day
(DateSerial(Year(Date()),Month(Date()),1)-1)
Instead of DateSerial(Year(Date()),Month(Date())-1,31)
- as pointed by @topsail, this is probably incorrect.
Conditions like
tracking.Date Between DateSerial(Year(Date()),1,1)
And (DateSerial(Year(Date()),Month(Date()),1)-1)
can be simplified as
tracking.Date <=(DateSerial(Year(Date()),Month(Date()),1)-1)
because you have condition in WHERE clause
(([Tracking]![Date] Between DateSerial(Year([Date]),1,1) And DateSerial(Year([Date]),12,31)))
See example
SELECT Tracking.Name, Sum(Tracking.Price) AS CurTotal
,Sum(IIf(tracking.Date Between DateSerial(Year(Date()),1,1)
And (DateSerial(Year(Date()),Month(Date()),1)-1),tracking.price,0)) AS PreMonth
,Sum(IIf(tracking.Date Between DateSerial(Year(Date()),1,1)
And (DateSerial(Year(Date()),Month(Date())+1,1)-1),tracking.price,0)) AS CurPay
,Sum(IIf(tracking.Date Between DateSerial(Year(Date()),1,1)
And (DateSerial(Year(Date()),Month(Date())+1,1)-1),IIF(tracking.price>0,tracking.price,0),0)) AS CurPayPlus
FROM Tracking
WHERE (([Tracking]![Date] Between DateSerial(Year([Date]),1,1) And DateSerial(Year([Date]),12,31)))
GROUP BY Tracking.Name;