Reputation: 67
In this specific part of a SP I'm trying to create, I'm getting an error:
[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Divide by zero error encountered. Additional error <2>: ErrorMsg: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Warning: Null value is eliminated by an aggregate or other SET operation., SqlState: 01003, NativeError: 8153
I believe this is because I'm trying to divide by a null or 0. I'm unsure how I can work around this. I tried to use ISNULL but I think I'm not doing it right.
select
id_date,
id_company,
id_kpi,
sum(CASE WHEN id_kpi=50 THEN -actual_mes END) /
sum(CASE WHEN id_kpi=51 THEN actual_mes END) Amount
from dual;
Can someone point me in the right direction? I've looked at a few other threads on this, but I'm still not sure how to solve this.
Upvotes: 1
Views: 12329
Reputation: 419
I put together a safe-divide function as we do a lot of dividing with our invoice data, and it saves from having to add conditionalized fluff when building our queries. Instead, just call the function with your enumerator and denominator and it will return 0 if your denominator is either 0 or NULL. You can adjust the @Return to a different data type if you wish (i.e. FLOAT) so it's a bit more apples to apples with the input...we just usually only need it to 4 decimals so we normalized it to that instead.
IF OBJECT_ID('dbo.fn_SafeDivide') IS NOT NULL
DROP FUNCTION dbo.fn_SafeDivide
GO
CREATE FUNCTION dbo.fn_SafeDivide(
@Numerator FLOAT,
@Denominator FLOAT
)
RETURNS DEC(14,4)
AS
BEGIN
DECLARE @Return DEC(14,4)
IF COALESCE(@Denominator, 0) = 0
SET @Return = 0
ELSE
SET @Return = @Numerator / @Denominator
RETURN @Return
END
GO
To Use:
select
dbo.fn_SafeDivide(
SUM(CASE WHEN id_kpi=50 THEN -actual_mes END),
SUM(CASE WHEN id_kpi=51 THEN actual_mes END)
) as Amount
from dual;
Upvotes: 0
Reputation: 41
You can use case when .. else ... end
and isnull
e.g.
select
id_date,
id_company,
id_kpi,
CASE WHEN ISNULL(sum(CASE WHEN id_kpi=51 THEN ISNULL(actual_mes, 0) ELSE 0 END), 0) = 0
THEN 0
ELSE
sum(CASE WHEN id_kpi=50 THEN -ISNULL(actual_mes, 0) ELSE 0 END) /
sum(CASE WHEN id_kpi=51 THEN ISNULL(actual_mes, 0) ELSE 0 END)
END Amount
from dual;
Upvotes: 0
Reputation: 81970
Rather than the CASE
, I usually opt for NullIf()
on the denominator
Example
select id_date,
id_company,
id_kpi,
sum(CASE WHEN id_kpi=50 THEN -actual_mes END) /
nullif(sum(CASE WHEN id_kpi=51 THEN actual_mes END),0) Amount
from dual;
Upvotes: 3