2013-10-28 2 views
10

У меня есть SQL-запрос, который использовался для возникновения исключения Divide By Zero, я завернул его в оператор CASE, чтобы это не происходило. Есть ли более простой способ сделать это?Простой способ предотвратить ошибку Divide By Zero в SQL

Вот мой код:

Percentage = CASE WHEN AttTotal <> 0 THEN (ClubTotal/AttTotal) * 100 ELSE 0 END 
+1

Это зависит от того, как вы wan't ваш запрос и результат себя, когда 'AttTotal' является 0 или NULL, так что нет общего пути делать это. Я бы сказал, что ваш запрос в порядке. Даже если вы будете писать свой запрос по-разному, используя 'ISNULL' или' NULLIF' в конце, он, скорее всего, выполнит то же самое. –

+0

Как было указано другими, логика в этом заявлении CASE не имеет для нас никакого смысла. См. Мой комментарий к моему ответу для краткого объяснения, а затем выберите, хотите ли вы свой первоначальный ответ или мой. Мой ответ был бы более обычным решением. –

+1

Возможный дубликат [Как избежать ошибки «делить на ноль» в SQL?] (Http://stackoverflow.com/questions/861778/how-to-avoid-the-divide-by-zero-error-in- sql) –

ответ

36

приятнее способ сделать это состоит в использовании NULLIF так:

Percentage = 100 * ClubTotal/NULLIF(AttTotal, 0) 
+3

Это вернет 'NULL', если' AttTotal = 0', в то время как запрос, о котором идет речь, возвращает 0. –

+4

@NenadZivkovic - Возвращение 'NULL' для деления на нулевую ошибку, вероятно, делает еще более математический смысл. –

+0

Я согласен с @ Мартином Смитом. Если у вас есть ситуация, когда ClubTotal является числом, а AttTotal равен нулю, нет смысла возвращать ноль. Или любое другое число :-) Возвращающий нуль означает, что ClubTotal равен нулю, а AttTotal больше нуля. –

5
Percentage = IsNull(ClubTotal/NullIf(AttTotal, 0) * 100, 0) 
+0

Не совсем то же, что и запрос в вопросе. Если значение 'AttTotal' или' ClubTotal' равно 'NULL', это также вернет' 0'. –

+1

Согласитесь, мне нравится @Dommer, несмотря на то, что он не сохраняет и оригинальную логику. –

1

На мой взгляд, заявление СЛУЧАЙ именно так идти. Вместо вычисления чего-либо вы указываете значение, возвращаемое для случая, когда AttTotal равен нулю. Вы даже можете добавить другую ветвь case для 0 из 0, равную 100%.

Только боковое примечание: я бы не вернулся 0, когда AttTotal равен нулю, а ClubTotal больше нуля. NULL может быть более уместным. Или вы можете создать строки (например, '10 .50% '), а не число (например, 10,5%), не содержащие в случае AttTotal равны нуль „Нет ATT тотального.“:

PercentageString := 
    CASE 
    WHEN AttTotal = 0 AND ClubTotal = 0 then '100%' 
    WHEN AttTotal = 0 AND ClubTotal <> 0 THEN 'No att. total' 
    ELSE to_char(ClubTotal/AttTotal * 100) || '%' 
    END; 
7

Я использую NULLIF немного по-другому, потому что в некоторых случаях мне приходится возвращать некоторую ценность. Обычно мне нужно возвращать 0, когда есть деление на нулевую ошибку. В этом случае я завершаю все выражение в ISNULL. Поэтому было бы:

Percentage = ISNULL(100 * ClubTotal/NULLIF(AttTotal, 0), 0) 

Внутренняя часть оценивается в NULL, а затем ISNULL заменяет его 0.

0

Решение, которое я нашел, чтобы справиться с Деление на ноль проблемы создать функцию, что я может потребовать решения ситуации, поскольку мне часто приходится выполнять какой-то анализ соотношения/процентного типа. Вот простая функция, которую я написал.

Create Function fnRatio(@Numerator decimal(10,2),@Demoninator decimal(10,2)) 

Returns decimal(10,2) 

Begin 

Return 

Case 

     When @Demoninator = 0 then 0.00 



     When @Demoninator Is Null then Null 



Else 

     @Numerator/@Demoninator 

End 

Конец

С уважением

Джейсон

Смежные вопросы