SQL Server:如何在查询中处理除以0的情况

时间:2010-08-18 19:52:00

标签: sql-server-2005 aggregate-functions divide-by-zero

我有一个看起来像这样的查询,并且获得了一个百分比:

SELECT SUM(convert(decimal(3,2),
          CASE WHEN Status_ID = 1 AND State_ID = 14 THEN 1 ELSE 0 END))/
          SUM(convert(decimal(3,2),CASE WHEN State_ID = 14 THEN 1 ELSE 0 END)) * 100
FROM SomeTable

在正常情况下,这可能会返回59.77803之类的内容。但是,当第二个SUM - 分母 - 可能为0时,有(正确的)情况。是否有人知道如何解释这种情况并避免除以0异常?

我正在使用SQL Server 2005.谢谢。

6 个答案:

答案 0 :(得分:2)

我可能会使用NULL来表示不可计算的,但这取决于您在问题域中的意图(扩展代码以显示正在发生的事情):

SELECT SUM(convert(decimal(3,2),
                   CASE WHEN Status_ID = 1 AND State_ID = 14 THEN 1 ELSE 0 END)
          )
       /
       NULLIF(
           SUM(convert(decimal(3,2),
                       CASE WHEN State_ID = 14 THEN 1 ELSE 0 END)
           )
           , 0
       )
       * 100
FROM SomeTable

当表中没有行使分母为零时的结果 - 转换为NULL,因此整个表达式最终为NULL。

该代码也可以简化一点(可能因为它已经是一个简化的玩具问题):

SELECT SUM( convert(decimal(3,2), CASE WHEN Status_ID = 1 THEN 1 ELSE 0 END) )
       /
       NULLIF( convert(decimal(3,2), COUNT(*)), 0 )
       * 100
FROM SomeTable
WHERE State_ID = 14

作为将多个不同事物组合到一个查询中的示例:

SELECT CASE WHEN State_ID = 14 THEN 'State_ID = 14'
            WHEN State_ID IN (1, 2, 3) THEN 'State_ID IN (1, 2, 3)'
            ELSE 'DEFAULT'
       END AS Category
       ,SUM(convert(decimal(3,2),
                   CASE WHEN Status_ID = 1 THEN 1 ELSE 0 END)
          )
       /
       convert(decimal(3,2), COUNT(*))
       * 100
FROM SomeTable
GROUP BY CASE WHEN State_ID = 14 THEN 'State_ID = 14'
            WHEN State_ID IN (1, 2, 3) THEN 'State_ID IN (1, 2, 3)'
            ELSE 'DEFAULT'
       END

答案 1 :(得分:1)

问问自己,当分母为0时,你想要返回的结果是什么? 然后根据它相应地修复查询。

没有好的内置方式来做到这一点。这是一个商业逻辑。

答案 2 :(得分:1)

如果我正确阅读,这应该有效:

SELECT SUM(convert(decimal(3,2), 
          CASE WHEN Status_ID = 1 THEN 1 ELSE 0 END))/ 
          SUM(convert(decimal(3,2),1)) * 100 
FROM SomeTable 
WHERE State_ID = 14 

答案 3 :(得分:0)

SELECT SUM(convert(decimal(3,2),
          CASE WHEN Status_ID = 1 AND State_ID = 14 THEN 1 ELSE 0 END))/
          SUM(convert(decimal(3,2),CASE WHEN State_ID = 14 THEN 1 ELSE 0 END)) + 0.00000000001 * 100
FROM SomeTable

答案 4 :(得分:0)

为了避免除以0异常,你可以使用一个函数,当分母为0时,它接受分子,分母和默认值。并调用该函数进行除法。

CREATE FUNCTION [dbo].[fn_divide] 
(
    @numerator DECIMAL(3,2),@denominator DECIMAL(3,2),@default DECIMAL(3,2)
)  
RETURNS DECIMAL(3,2) 

AS  BEGIN

 DECLARE @result DECIMAL(3,2)

 IF @denominator = 0
 BEGIN
    set @result=@default
 END
ELSE
 BEGIN
    set @result=@numerator/@denominator
 END 

  return @result
END

答案 5 :(得分:0)

真正的问题是当你试图除以零时,“答案”应该是什么?我会把它NULL,所以尝试这样的事情:

DECLARE @x int

set @x=5
select 1.0/NULLIF(@x,0)

set @x=0
select 1.0/NULLIF(@x,0)

输出:

---------------------------------------
0.200000000000

(1 row(s) affected)


---------------------------------------
NULL

(1 row(s) affected)

您的代码将是:

SELECT SUM(convert(decimal(3,2), CASE
                                     WHEN Status_ID = 1 AND State_ID = 14 THEN 1 
                                     ELSE 0 
                                 END
                  )
          ) 
        /
        SUM(convert(decimal(3,2),CASE
                                     WHEN State_ID = 14 THEN 1 
                                     ELSE NULL   --<<<<<<<<<<<<force null if div by zero
                                 END
                   )
           )
        * 100
FROM SomeTable

我真的不理解WHEN Status_ID = 1 AND State_ID = 14 THEN 1,但那是OP代码。