Through the following query, I am able to get the total for the current month from a data table.
SELECT SUM(MONTODEBITO) - SUM(MONTOCREDITO)
FROM PRUEBAOPEX
WHERE MONTH(FECHA) = 1 AND YEAR(FECHA) = 2021
Since I am working inside a stored procedure, I have declared a variable that is equal to the following query.
CREATE PROCEDURE SP_VALORS
(@NIVEL VARCHAR(15),
@MES INT,
@AÑO INT)
AS
BEGIN
DECLARE @TOTALMESACTUAL FLOAT, @TOTALMESPASADO FLOAT
SET @TOTALMESACTUAL = (SELECT SUM(MONTODEBITO) - SUM(MONTOCREDITO)
FROM PRUEBAOPEX
WHERE MONTH(FECHA) = @MES
AND YEAR(FECHA) = @AÑO)
END
When executing the procedure, it returns the value correctly.
I also need to declare another variable that displays the total for the month before the month I pass as a parameter in my procedure.
I have the following example:
SELECT SUM(MONTODEBITO) - SUM(MONTOCREDITO)
FROM PRUEBAOPEX
WHERE MONTH(FECHA) = 2-1 AND YEAR(FECHA) = 2021
When I send 2 (February) to 12 (December) as a parameter, it shows me correctly.
More than all my doubt is in the case of sending 1 (January) as a parameter. It should show me the total for December of the previous year. How could I declare this variable?
Thank you for any help you may receive.
CodePudding user response:
You should be using date boundaries, not using syntax like WHERE MONTH(SomeDate) = @SomeMonthNumber
. This means you can make a SARGable query, and you can easily apply better logic to the date boundary you want.
An easy way to get a date from a month and year value is to use DATEFROMPARTS
. As you want the whole of a specific month, you can use 1
for the day of the month.
After making some other changes, as there are some odd choices in your procedure (variables that are declared and not used, a lack of the procedure returning anything), I suspect you want something like this:
--I have dropped the prefix as I recommend in the comments of your prior question.
CREATE PROCEDURE dbo.VALORS @NIVEL varchar(15), @MES int, @AÑO int, @TOTALMESACTUAL float = NULL OUTPUT AS
BEGIN
SELECT @TOTALMESACTUAL = SUM(MONTODEBITO - MONTOCREDITO) --There's no need for a subquery here
FROM dbo.PRUEBAOPEX
WHERE FECHA >= DATEFROMPARTS(@AÑO, @MES, 1)
AND FECHA < DATEADD(DAY, 1, DATEFROMPARTS(@AÑO, @MES, 1));
END;
If you wanted to get the prior month, you can easily apply a further DATEADD
to subtract a month from the expression (DATEADD(MONTH, -1, <Expression>)
).
Also, I suspect that float
is not the right choice for your data type, and that a base-10 data type would be better; though without knowing what SUM(MONTODEBITO - MONTOCREDITO)
represents, I haven't changed the data type.
CodePudding user response:
You will get better performance from the current code by changing it like this:
DECLARE @Month DateTime = DatefromParts(@AÑO, @MES, 1)
SET @TOTALMESACTUAL = (SELECT SUM(MONTODEBITO) - SUM(MONTOCREDITO)
FROM PRUEBAOPEX
WHERE @Month <= FECHA and FECHA < Dateadd(month, 1, @Month)
)
The improved performance is because the FECHA
column now remains unaltered for the query, and will therefore work better (at all) with any indexes you have.
More importantly, this is also very easy to convert to get the previous month:
DECLARE @Month DateTime = DatefromParts(@AÑO, @MES, 1)
Set @Month = DATEADD(month, -1, @Month)
SET @TOTALMESACTUAL = (SELECT SUM(MONTODEBITO) - SUM(MONTOCREDITO)
FROM PRUEBAOPEX
WHERE @Month <= FECHA and FECHA < Dateadd(month, 1, @Month)
)