除以零错误遇到错误。通过聚合或其他 SET 操作消除空值
Divide by zero error encountered error. Null value is eliminated by an aggregate or other SET operation
在我尝试创建的 SP 的这个特定部分,我遇到了一个错误:
[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
我相信这是因为我试图除以 null 或 0。我不确定如何解决这个问题。我尝试使用 ISNULL,但我认为我做的不对。
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;
有人能指出我正确的方向吗?我已经查看了其他几个与此相关的话题,但我仍然不确定如何解决这个问题。
您可以使用 case when .. else ... end
和 isnull
,例如
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;
而不是 CASE
,我通常在分母上选择 NullIf()
例子
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;
我将一个安全除法函数放在一起,因为我们对发票数据进行了很多除法,它避免了在构建查询时必须添加条件化的绒毛。相反,只需使用您的枚举数和分母调用该函数,如果您的分母为 0 或 NULL,它将 return 0。如果您愿意,您可以将 @Return 调整为不同的数据类型(即 FLOAT),这样输入就更合适了……我们通常只需要 4 位小数,所以我们将它标准化为相反。
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
使用:
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;
在我尝试创建的 SP 的这个特定部分,我遇到了一个错误:
[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
我相信这是因为我试图除以 null 或 0。我不确定如何解决这个问题。我尝试使用 ISNULL,但我认为我做的不对。
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;
有人能指出我正确的方向吗?我已经查看了其他几个与此相关的话题,但我仍然不确定如何解决这个问题。
您可以使用 case when .. else ... end
和 isnull
,例如
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;
而不是 CASE
,我通常在分母上选择 NullIf()
例子
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;
我将一个安全除法函数放在一起,因为我们对发票数据进行了很多除法,它避免了在构建查询时必须添加条件化的绒毛。相反,只需使用您的枚举数和分母调用该函数,如果您的分母为 0 或 NULL,它将 return 0。如果您愿意,您可以将 @Return 调整为不同的数据类型(即 FLOAT),这样输入就更合适了……我们通常只需要 4 位小数,所以我们将它标准化为相反。
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
使用:
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;