简体   繁体   中英

Include zero figures in calculation without getting divide by zero errors

I am attempting to calculate the average of a percentage that needs to take into account percentages that are zero.

I am currently using the following formula to exclude those that will ultimately end up as zero, but this is skewing the figures.

  SET     Average = (SELECT ROUND(AVG((CAST(Figure1 AS FLOAT)/CAST(Figure2 AS FLOAT))*100),2)
                              FROM       [Schema].[Table] m
                              WHERE      m.Figure1 > 0 and m.Figure2 > 0)

When I include the possible zero based percentages

  SET     Average = (SELECT ROUND(AVG((CAST(Figure1 AS FLOAT)/CAST(Figure2 AS FLOAT))*100),2)
                              FROM       [Schema].[Table] m)

I obviously get the following error;

Divide by zero error encountered. The statement has been terminated.

How can I change this to include the zero based percentages without the error?

The problem would be dividing by zero - so only figure2 is relevant which is the divident.

Use a case statement to set a static value for that specific case (I chose 0 ):

SET Average = (SELECT ROUND(AVG(case when Figure2 = 0
                                     then 0
                                     else CAST(Figure1 AS FLOAT) / CAST(Figure2 AS FLOAT)
                                end * 100)
                            ,2)
               FROM [Schema].[Table] m)

One good way to prevent divide by zero is to use the NULLIF function, like this:

 SET     Average = (SELECT ROUND(AVG((CAST(Figure1 AS FLOAT)/NULLIF(CAST(Figure2 AS FLOAT), 0))*100),2)
                              FROM       [Schema].[Table] m)

Using the NULLIF method, the value NULL would be returned for the row(s) where Figure2 is 0. The AVG function ignores NULL values. Because of this, please consider carefully whether this is the solution you want to use (because the results may be different than what you expect).

Well, the real problem is that division by zero produce undefined results, so they should not be part of any calculation.

If you do decide to factor them in, you'll have to give them some nominal value. Let's say you want to use "zero" as that nominal value: you could do something like this:

SELECT @average = 
   AVG(   CASE
             WHEN COALESCE(CAST(figure2 AS Float), 0) = 0 THEN 0.0
             ELSE COALESCE(CAST figure1 AS Float), 0) / CAST(figure2 AS Float)
           END
       )
  FROM MyTable 
 WHERE Blah Blah Blah

While the answer of

SET Average = (SELECT ROUND(AVG(case when Figure2 = 0
                                 then 0
                                 else CAST(Figure1 AS FLOAT) / CAST(Figure2 AS FLOAT)
                            end * 100)
                        ,2)
           FROM [Schema].[Table] m)

is good if you want the records where Figure2 is zero to be average in as a zero, but I personally wouldn't want them at all and would use

SET Average = (SELECT ROUND(AVG(CAST(Figure1 AS FLOAT) / CAST(Figure2 AS FLOAT)
                             * 100)
                        ,2)
           FROM [Schema].[Table] m where Figure2 <> 0 and Figure2 is not null)

or perhaps this is a bonus points situation where you really have 4 points out of 0 points. Then I would do the following. Still taking into account if Figure2 really has all zeros in it's results.

SET Average = ((SELECT CASE WHEN (SUM(CAST(Figure2 AS FLOAT))) <> 0 
           THEN ROUND(SUM(CAST(Figure1 AS FLOAT)) / SUM(CAST(Figure2 AS FLOAT))
           * 100
          ,2) ELSE 0 END
          FROM [Schema].[Table] m)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM