Home > database >  How to get the total of a previous month having passed the current month as a parameter in a SQL Ser
How to get the total of a previous month having passed the current month as a parameter in a SQL Ser

Time:02-02

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.

enter image description here

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)
)
  • Related