Divide by zero error encountered, but should be excluded by CASE - sql

I have the following code and I am getting an error:
Divide by zero error encountered.
SELECT
CASE WHEN SUM([monthly_qty]) = 0 THEN 999
ELSE ROUND(SUM([monthly_buy] * ([monthly_markup]+100)/100),2) * SUM([monthly_qty] / [monthly_qty]) END as [monthly_total]
FROM [xxxxx].[dbo].[quote_items] WHERE docid='10152'
The field that is causing the error is the second [monthly_qty], just before the END of the CASE statement.
SUM([monthly_qty] / **[monthly_qty]**)
The value of monthly_qty is zero, so the error makes sense, but I am confused as this field is inside the CASE statement, so the expected result is 999
Any help greatly appreciated.

I can't understand reason of some parts of your code like this:
SUM([monthly_qty] / [monthly_qty])
The result is error when [monthly_qty] = Zero, And 1 for non zero.
Anyway, You can set a default value When "monthly_qty" is zero:
IIF([monthly_qty]= 0,'YOUR_DEFAULT_VALUE', [monthly_qty] / [monthly_qty])
Then:
SUM(IIF([monthly_qty]= 0,'YOUR_DEFAULT_VALUE', [monthly_qty] / [monthly_qty]))

Have a read at MS Docs, there is an example of your case under Remarks.
The CASE expression evaluates its conditions sequentially and stops
with the first condition whose condition is satisfied. In some
situations, an expression is evaluated before a CASE expression
receives the results of the expression as its input. Errors in
evaluating these expressions are possible. Aggregate expressions that
appear in WHEN arguments to a CASE expression are evaluated first,
then provided to the CASE expression. For example, the following query
produces a divide by zero error when producing the value of the MAX
aggregate. This occurs prior to evaluating the CASE expression.

The reason is simple. This code:
SUM([monthly_qty]) = 0
Does not prevent a divide-by-zero in this code:
SUM([monthly_qty] / [monthly_qty])
The expressions are different.
The simplest solution (and essentially the "standard" approach) is to use NULLIF():
SUM([monthly_qty] / NULLIF([monthly_qty], 0))
However, I wonder if you really intend:
SUM([monthly_qty]) / NULLIF(SUM([monthly_qty]), 0)

Related

SQL Error in Non Case condition of CASE WHEN clause

I tried executing the following SQL statement.
SELECT CASE WHEN CHARINDEX('~','test.pdf') > 0
THEN SUBSTRING('test.pdf',CHARINDEX('~', 'test.pdf'), -10)
ELSE NULL
END
This resulted in an error 'Invalid length parameter passed to the substring function.'. However, this was not expected because it is not going to execute anyway.
This query is a simplified version of my requirement. Actually we are computing the value length for the substring. The real scenario is also given below :
SELECT CASE
WHEN CHARINDEX('~', 'test.pdf') > 0 THEN SUBSTRING('test.pdf', CHARINDEX('~', 'test.pdf') + 1, CHARINDEX('~', 'test.pdf', (CHARINDEX('~', 'test.pdf', 1)) + 1) - CHARINDEX('~', 'test.pdf') - 1)
ELSE NULL
END;
In the example its hardcoded as 'test.pdf' but in real scenario it would be values like '111111~22222~33333~4444.pdf' from Table column. Also, I'm not sure this file name should always follow this format. Hence, a validation is required.
Actually, the computation for length is quite expensive, and don't want to use it twice in this query.
You have passed -10 as a constant to substring(). This function does not allow negative values for the third argument:
length
Is a positive integer or bigint expression that specifies how many characters of the expression will be returned. If length is negative, an error is generated and the statement is terminated. If the sum of start and length is greater than the number of characters in expression, the whole value expression beginning at start is returned.
SQL Server catches this problem during the compile phase. This has nothing to do with CASE expression evaluation, but with parsing the expressions.

isnull(#variable, 1) but for 0 instead of null

I have an equation that multiplies loads of variables together, if one of those variables is 0 then I don't want it included in the equation by substituting it for 1 which won't affect the result.
A case when - then, statement for each variable validating if they're greater than 0is a bit clunky.
Is there a similar function like IsNull where if the variable is 0 then it returns an alternate value?
--edit #Backs answer is right but apparently after sql 2012 iif was taken out, when i try to write the statement there is a syntax error at the '=' sign. Is there a replacement for iif after sql-2012?
IIF(#variable = 0, 1, #variable)

access statement convert to Sql

how can I convert to T-Sql this one?
IIf([ESSValue]<>0,Int([ESSValue]*100),"")
I think the following pretty much does what you want:
select coalesce(cast(EssValue * 100 as int), 0)
Here is the thinking. The comparison to zero is unimportant, because 0 times any value is going to be zero. The iif() returns an integer (I think) because the "then" argument is an integer; the empty string gets converted to zero.
I'm not 100% certain about the last statements with regard to MS Access, but that is how iif() works in SQL Server.
I should add. Although I don't approve of iif() for conditional expressions (because case is the standard and more powerful), SQL Server does support it. So you could write:
IIf([ESSValue]<>0, cast([ESSValue]*100 as int), '')
Note: As I mentioned earlier, the '' will be converted to 0.
CASE WHEN ESSValue <> 0
THEN CAST(ESSValue * 100 AS INT)
ELSE NULL
END as fieldname
For case expression the default is NULL if doesn't meet any condition, so you dont really need the ELSE condition

Division in SQL Server

I am trying to use division in SQL Server. I have tried the code snippet below.
SELECT m.[Profit] / f.[Target]
And I have also tried
SELECT SUM(m.[Profit] / f.[Target])
but I get the error
Divide by zero error encountered.
Warning: Null value is eliminated by an aggregate or other SET operation.
What is the reason for this and how can I fix it? Suggested fixes online say that this code should work but it doesn't.
Thanks
Use NULLIF to avoid divided by zero exception
SELECT SUM(m.[Profit] / NULLIF(f.[Target],0))
When denominator is zero then it will be replaced with NULL
If I were trying to determine the % of a goal (inferred by profit /target columns), I would try something like:
SELECT
CASE WHEN ISNULL(f.[Target],0) = 0 THEN NULL -- or whatever you need to return when the target value is undefined, or it is 0
ELSE m.[Profit] / f.[Target] END AS [result]
The error you get specifies exactly what is the problem. Your code is trying to divide by zero, which is mathematically impossible.
Please NULLIF to avoid this error.

T-SQL 2005 - Divide by zero error encountered

I am trying to get some percentage data from a stored procedure using code similar to the line below. Obviously this is going to cause a (Divide by zero error encountered) problem when base.[XXX_DataSetB] returns 0 which may happen some of the time.
Does anyone know how i can deal with this in the most efficient manner?
Note: There would be about 20+ lines looking like the one below...
cast((base.[XXX_DataSetB] - base.[XXX_DataSetA]) as decimal) /
base.[XXX_DataSetB] as [XXX_Percentage]
I guess it depends on what behaviour you expect when XXX_DataSetB is zero.
If you don't want any rows returned that might cause an error, you can easily filter out those rows by adding where XXX_DataSetB <> 0 to your query.
If you would like problem rows to be NULL then you could use a case statement, or something like this:
cast(([XXX_DataSetB] - [XXX_DataSetA]) as decimal) / nullif([XXX_DataSetB], 0)
I'd force the average to null by making the bottom term null instead of zero:
cast((base.[XXX_DataSetB] - base.[XXX_DataSetA]) as decimal)
/ case when base.[XXX_DataSetB] = 0 then null
else base.[XXX_DataSetB] end as [XXX_Percentage]