i used nullif and got sql divide by zero error - sql-server

select STORECODE,
ItemCode,
ColorCode,
ToplamStok,
ToplamSatis,
(CASE WHEN ToplamSatis = 0
THEN ISNULL(ToplamStok/NULLIF(ToplamSatis,0.1)*7,0)
ELSE (ToplamStok/ToplamSatis)*7
end) as SDH
into #SatisStokSDH
from #SatisStok
for this query, I'm getting this error : Divide by zero error encountered.
why am i getting this, i already used isnull function?
Thanks in advance.

Your problem is that when ToplamSatis happens to be zero, you are still dividing by zero:
NULLIF(ToplamSatis, 0.1)
The above would replace ToplamSatis with 0.1, but only if the former were NULL, not if it were zero. Try the following CASE logic:
CASE WHEN ToplamSatis = 0
THEN ISNULL((ToplamStok / 0.1)*7, 0) -- not sure if need to wrap with ISNULL
ELSE (ToplamStok / ToplamSatis)*7
END

Related

What does CASE SUM(total_of_A) WHEN 0 THEN 0 ELSE SUM(B) / SUM(total_of_A) END mean

Trying to understand the CASE (Transact-SQL) expression, but ended up with lot of confusion. Can anyone please explain the following statement in simple words?
CASE SUM(total_of_A) WHEN 0 THEN 0 ELSE SUM(B) / SUM(total_of_A) END;
I read the following, but it doesn't clear up the confusion
CASE input_expression
WHEN when_expression THEN result_expression [ ...n ]
[ELSE else_result_expression ]
END
It means
Calculate SUM(B) / SUM(total_of_A) only if the sum of total_of_A is not 0 because that would lead to a divide by zero exception.
It works like this
case <check SUM(total_of_A)>
when <result of check is 0?>
then <output 0>
else <output the result of SUM(B) / SUM(total_of_A)>
end
In SQL Server dividing by zero causes the following error:
Msg 8134, Level 16, State 1, Line 1
Divide by zero error encountered.
So, the case statement is use for avoiding such cases.
Anyway, I guess this is wrong as value / 0 is not 0. I like the following check more:
SUM(B) / NULLIF(SUM(total_of_A), 0)
as it is shorter and returns NULL instead.
This reads as
If the sum of the column named total_of_A is 0 then the result of this case statement is 0 else the result of this case statement is the sum of the column named b divided by the sum of the column named total_of_A

SQL Server : divide by zero error

I have searched the forums and found several responses on this topic but as I am new to SQL I'm not getting it.
I created a TSQL query that when run returns "Divide by zero error". This is because I am dividing one column by another and there is a zero in one of the records. Ok, I got that part but I can't make heads or tails of the posts explaining how to resolve the issue.
SELECT
f.Sales_Rep1 AS 'Sales Rep'
, SUM(CAST(f.Other1_Revenue + f.Other2_Revenue AS FLOAT)) AS 'MRR'
, CW.MRR_Goal AS 'MRR Goal'
, SUM((f.Other1_Revenue + f.Other2_Revenue)/(CW.MRR_Goal)) AS 'Total'
, SUM(CAST(f.Product_Revenue + f.Service_Revenue AS FLOAT)) AS 'NRR'
, CW.NRR_Goal AS 'NRR Goal'
, (cw.MRR_Goal + cw.NRR_Goal)AS 'Total Goal'
FROM
dbo.v_rpt_Opportunity AS f
INNER JOIN
dbo.v_memberpickerlist AS m ON f.Sales_Rep1 = m.Member_ID
INNER JOIN
dbo.CW_SalesGoals AS CW ON CW.Sales_Rep = f.Sales_Rep1
WHERE
(f.Expected_Close_Date >= DATEADD(MM, DATEDIFF(MM, 0, GETDATE()), 0))
AND (m.activestatus = 'active') AND (f.Status = 'Won')
OR (f.Expected_Close_Date >= DATEADD(MM, DATEDIFF(MM, 0, GETDATE()), 0))
AND (m.activestatus = 'active')
AND (f.Status LIKE '%submitted%')
GROUP BY
f.Sales_Rep1, CW.MRR_Goal, CW.NRR_Goal,
f.Other1_Revenue, f.Other2_Revenue
I know the line that is causing the issue, but I do not know how to resolve it...
SUM((f.Other1_Revenue + f.Other2_Revenue) / (CW.MRR_Goal)) AS 'Total'
What I am trying to do is get the percentage of the goal but I cant get past the division to do that.
Any help would be greatly appreciated. Thank you!
You can use the nullif() function to avoid divide by zero exceptions:
(f.Other1_Revenue + f.Other2_Revenue) / nullif(CW.MRR_Goal, 0)
In the event that CW.MRR_Goal is 0, the result for the entire expression will be null1.
Sample:
select 1 / nullif(0, 0) -- null
1 I've selected null because, in my opinion, it's the most appropriate analogue for undefined in SQL. While that's helpful for an individual expression, it may not be what you're looking for in an aggregate sense.
Use a CASE statement:
SUM(CASE WHEN CW.MRR_Goal <> 0 THEN (f.Other1_Revenue + f.Other2_Revenue)/(CW.MRR_Goal) ELSE 0 END) AS 'Total'
This way, it will perform the division only if the value of CW.MRR_Goal in that record is other than zero; if it's zero, it will return 0
You could use an IIF:
SUM(IIF(CW.MRR_Goal = 0, 0, (f.Other1_Revenue + f.Other2_Revenue) / (CW.MRR_Goal))
This way if the goal is equal to 0 then it will SUM the 0 rather than trying the division whereas if the goal is not equal to 0 then it will do the division.
More on IIF https://msdn.microsoft.com/en-GB/library/hh213574.aspx
As user3540365 mentioned IIF only applies from SQL Server 2012 as opposed to CASE which applies from SQL Server 2008 onwards see here and is an SQL standard.

How do I do decimal arithmetic on two varchars and return result to an aliased column?

I have two fields of type varchar that contain numeric values or blank strings, the latter of which I have filtered out to avoid Divide by Zero errors.
I am attempting to determine the percentage value that num2 represents in relation to num1, i.e. (Num_2 * 1 / Num_1). Relatively simple math.
The problem I am having is that I cannot seem to do the math and then cast it to a decimal value. I keep receiving Arithmetic overflow error converting int to data type numeric errors.
Can someone help me out with the casting issue?
You didn't interpret the error correctly.
It is not about casting the result of your math to float, it is about implicit type casting before the equation is evaluated.
You have in your table some values that cannot be converted to numeric, because they are not valid numbers or numbers out of range. It is enough that one row contains invalid data to make fail the whole query.
perhaps you're looking for something similar to this?
declare #table table (
[numerator] [sysname]
, [denominator] [sysname]);
insert into #table
([numerator],[denominator])
values (N'1',N'2'),
(N'9999999999',N'88888888888');
select case
when isnumeric([numerator]) = 1
and isnumeric ([denominator]) = 1
then
cast([numerator] as [float]) / [denominator]
else
null
end
from #table;
Is this what you're looking for?
select cast('25.5' as decimal(15, 8)) / cast('100.0' as decimal(15, 8))
The example above will return this:
0.25500000000000000000000
In this case, I'm converting the operand types before they get used in the division.
Remember to replace the literals in my query by your field names.
you said that can be number or blank string.
son try something like this:
SELECT
(CASE WHEN NUM_2 = '' THEN 0 ELSE CAST(NUM_2 AS NUMERIC(15,4)) END)
/
(CASE WHEN NUM_1 = '' THEN 1 ELSE CAST(NUM_1 AS NUMERIC(15,4)) END)
you test if string is blank. if it is, you use 0 (or 1, to avoid division by zero)

How to protect sql statement from Divide By Zero error

I'm in the process of creating some reports that take a finite total (lets say 2,500) of products (for this example lets say Ice Cream Cones) and counts how many of them were broken before serving.
Now the actual count code of broken cones I've got down.
SELECT COUNT(broken_cones) FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'
However, I need a percentage of broken cones from this total as well. I've been playing around with the code but I keep running into a 'Divide By Zero' error with this code below.
SELECT CAST(NULLIF((.01 * 2500)/Count(broken_cones), 0) AS
decimal(7,4)) FROM [ice].[ice_cream_inventory] WHERE broken_cones = 'Yes'
For right now, there aren't any broken cones (and won't be for a while) so the total right now is zero. How can I show the NULL scenario as zero?
I tried to place an ISNULL statement in the mix but I kept getting the 'Divide by Zero' error. Am I even doing this right?
::edit::
Here's what I ended up with.
SELECT
CASE
WHEN COUNT(broken_cones) = 0 then 0
ELSE CAST(NULLIF((.01 * 2500)/Count(broken_cones), 0) AS decimal(7,4))
END
FROM [ice].[ice_cream_inventory] WHERE broken_cones = 'Yes'
Use a case statement.
SELECT
CASE WHEN COUNT(broken_cones) = 0 then 0
ELSE CAST(NULLIF((.01 * 2500)/Count(broken_cones), 0) AS decimal(7,4)) END
FROM [ice].[ice_cream_inventory] WHERE broken_cones = 'Yes'
You already have a solution, but this is why your original solution didn't work.
Your NULLIF needs to be moved in order to be effective. It is doing the division before it gets to the NULLIF call. Dividing by null will return a null value.
SELECT CAST((.01 * 2500)/NULLIF(Count(broken_cones), 0) AS decimal(7,4))
FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'`
The NULLIF() function is a great way to prevent divide by zero, since anything divide by NULL returns null. The way to use it is as follows:
<expression> / NULLIF( <expression>, 0 )
Unfortunately you've wrapped your whole divide expression in NULLIF() which is why it isn't working for you. So step one is to get it to return NULL if your COUNT() comes back zero:
SELECT
(0.01 * 2500) / NULLIF( COUNT(broken_cones), 0 )
FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'
Now you said you wanted that NULL to come back zero? That is where you use ISNULL():
ISNULL(<expression1>, <expression2>)
If the first expression is NULL then return the second expression, so our SQL now becomes:
SELECT
ISNULL(
(0.01 * 2500) / NULLIF( COUNT(broken_cones), 0 ),
0
)
FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'

Microsoft SQL: CASE WHEN vs ISNULL/NULLIF

Besides readability is there any significant benifit to using a CASE WHEN statement vs ISNULL/NULLIF when guarding against a divide by 0 error in SQL?
CASE WHEN (BeginningQuantity + BAdjustedQuantity)=0 THEN 0
ELSE EndingQuantity/(BeginningQuantity + BAdjustedQuantity) END
vs
ISNULL((EndingQuantity)/NULLIF(BeginningQuantity + BAdjustedQuantity,0),0)
Remember that NULL is different from 0. So the two code snippets in the question can return different results for the same input.
For example, if BeginningQuantity is NULL, the first expression evaluates to NULL:
CASE WHEN (NULL + ?)=0 THEN 0 ELSE ?/(NULL + ?) END
Now (NULL + ?) equals NULL, and NULL=0 is false, so the ELSE clause is evaluated, giving ?/(NULL+?), which results in NULL. However, the second expression becomes:
ISNULL((?)/NULLIF(NULL + ?,0),0)
Here NULL+? becomes NULL, and because NULL is not equal to 0, the NULLIF returns the first expression, which is NULL. The outer ISNULL catches this and returns 0.
So, make up your mind: are you guarding against divison by zero, or divison by NULL? ;-)
In your example I think the performance is negligible. But in other cases, depending on the complexity of your divisor, the answer is 'it depends'.
Here is an interesting blog on the topic:
For readability, I like the Case/When.
In my opinion, using Isnull/Nullif is faster than using Case When. I rather the isnull/nullif.
I would use the ISNULL, but try to format it so it shows the meaning better:
SELECT
x.zzz
,x.yyyy
,ISNULL(
EndingQuantity / NULLIF(BeginningQuantity+BAdjustedQuantity,0)
,0)
,x.aaa
FROM xxxx...
CASE WHEN (coalesce(BeginningQuantity,0) + coalesce(BAdjustedQuantity,0))=0 THEN 0 ELSE coalesce(EndingQuantity,0)/(coalesce(BeginningQuantity,0) + coalesce(BAdjustedQuantity,0)) END
your best option imho
Sorry, here is the little more simplify upbuilded sql query.
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]

Resources