2009-05-13 10 views
4

Outre la lisibilité, y at-il un avantage significatif à utiliser une instruction CASE WHEN par rapport à ISNULL/NULLIF lors de la sauvegarde contre une erreur de division par 0 dans SQL?Microsoft SQL: CASE WHEN vs ISNULL/NULLIF

CASE WHEN (BeginningQuantity + BAdjustedQuantity)=0 THEN 0 
ELSE EndingQuantity/(BeginningQuantity + BAdjustedQuantity) END 

vs

ISNULL((EndingQuantity)/NULLIF(BeginningQuantity + BAdjustedQuantity,0),0) 

Répondre

7

Rappelez-vous que NULL est différent de 0. Ainsi, les deux extraits de code dans la question peuvent retourner des résultats différents pour la même entrée.

Par exemple, si BeginningQuantity est NULL, la première expression est évaluée à NULL:

CASE WHEN (NULL + ?)=0 THEN 0 ELSE ?/(NULL + ?) END 

maintenant (? NULL +) est égal à NULL, NULL = 0 est faux, de sorte que la clause ELSE est évaluée, ce qui donne ?/(NULL +?), Ce qui aboutit à NULL. Cependant, la seconde expression devient:

ISNULL((?)/NULLIF(NULL + ?,0),0) 

Ici NULL +? devient NULL, et comme NULL n'est pas égal à 0, le NULLIF renvoie la première expression, qui est NULL. L'ISNULL externe l'attrape et renvoie 0.

Alors, décidez-vous: vous protégez-vous contre la divison par zéro, ou divison par NULL? ;-)

+0

Je finalement essayer de protéger contre la division par 0 –

+0

Le coût de la division éclipsera le coût des chèques de cas ou isNull, donc je prendrais la solution la plus facile à lire. Une autre option est une clause WHERE pour exclure les lignes qui se diviseraient par zéro. – Andomar

0

À mon avis, en utilisant isNull/NULLIF est plus rapide que l'utilisation de cas Lorsque. Je préfère l'isnull/nullif.

3

Dans votre exemple, je pense que la performance est négligeable. Mais dans d'autres cas, selon la complexité de votre diviseur, la réponse est «ça dépend».

Here is an interesting blog sur le sujet:

Pour faciliter la lecture, j'aime l'affaire/Quand.

0

j'utiliser le ISNULL, mais essayez de le formater afin qu'il montre mieux le sens:

SELECT 
    x.zzz 
     ,x.yyyy 
     ,ISNULL(
        EndingQuantity/NULLIF(BeginningQuantity+BAdjustedQuantity,0) 
       ,0) 
     ,x.aaa 
    FROM xxxx... 
0
CASE WHEN (coalesce(BeginningQuantity,0) + coalesce(BAdjustedQuantity,0))=0 THEN 0 ELSE coalesce(EndingQuantity,0)/(coalesce(BeginningQuantity,0) + coalesce(BAdjustedQuantity,0)) END 

votre meilleure option IMHO

0

Désolé, voici le petit plus de simplifier la requête upbuilded sql.

SELECT 

(ISNULL([k1],0) + ISNULL([k2],0))/

CASE WHEN (
(
    CASE WHEN [k1] IS NOT NULL THEN 1 ELSE 0 END + 
    CASE WHEN [k2] IS NOT NULL THEN 1 ELSE 0 END 
) > 0) 
THEN 
(
    CASE WHEN [k1] IS NOT NULL THEN 1 ELSE 0 END + 
    CASE WHEN [k2] IS NOT NULL THEN 1 ELSE 0 END 
) 
ELSE 1 END 

FROM dbo.[Table]