Redshift Divide By Zero Puzzler - sql

I was getting a divide by 0 error with this code:
CASE
WHEN DENOMINATOR >= 0
THEN SUM(INT1 * INT2 / DENOMINATOR)
ELSE 0
END AS RATIO
However when I changed to the following code, it worked.
CASE
WHEN DENOMINATOR >= 0
THEN SUM(INT1) * INT2 / DENOMINATOR
ELSE 0
END AS RATIO
Could someone help me understand the reason so I can avoid this in the future? BTW, the first sample worked in Vertica. I realize summing just what needs to be summed rather than doing the calculation before the summation is a better programming practice. However still am curious.

I think the best way to avoid divide-by-zero is to use nullif():
SUM(INT1 * INT2 / NULLIF(DENOMINATOR, 0))
or:
SUM(INT1) * INT2 / NULLIF(DENOMINATOR, 0)
This returns NULL, which I find more sensible for a divide-by-zero situation. You can add COALESCE() to get 0, if you like.

Related

Where to use NULLIF inside of a CASE WHEN?

I'm getting a divide by zero error when performing the below code. I have tried a NULLIF after the ELSE, but I am encountering the same error message:
SELECT
country_IBS
, Sku
, LTM_Sales_USD
, PTM_Sales_USD
, LTM_Cost_USD
, (CASE WHEN -([LTM_Sales_USD]-[PTM_Sales_USD])/([LTM_Sales_USD]+[PTM_Sales_USD]) IS NULL
THEN 0
ELSE -([LTM_Sales_USD]-[PTM_Sales_USD])/([LTM_Sales_USD]+[PTM_Sales_USD]) END +1)/2 AS "Sales Growth % (scaled)"
FROM #tempSalesChange
Wrap the divider in the NULLIF:
{Expression 1} / NULLIF({Expression 2},0)
That will mean that if the divider is 0 then NULL will be returned, and the divide by zero error will be avoided.
In your case, that's ([LTM_Sales_USD]+[PTM_Sales_USD]).
If suspect that you want:
(1 - ([LTM_Sales_USD] - [PTM_Sales_USD]) / NULLIF([LTM_Sales_USD] + [PTM_Sales_USD], 0)
) / 2 AS [Sales Growth % (scaled)]
That is: the divisor should be wrap in NULLIF(..., 0). This avoids the division by zero error - in that case, the whole computation returns NULL instead.

how to use is null with case statements

Hi can any one say me how to write query in sql server management studio for statement =>if(isnull("GROSS_SF")=1 or "GROSS_SF"=0,0,"GROSS_SALES"/"GROSS_SF")
by using case statement :
CASE
WHEN ("GROSS_SF"=1 or "GROSS_SF"=0) isnull then 0
else "GROSS_SALES"/"GROSS_SF"
end/* i am getting error if i write it like this */
thanks in advance
If you want to avoid a divide by zero, while at the same time also handling NULL, then you may try the following logic:
CASE WHEN COALESCE(GROSS_SF, 0) = 0
THEN 0
ELSE GROSS_SALES / GROSS_SF END AS output
To be clear, the above logic would return a zero value should either the GROSS_SF be zero or NULL.
I think what are you looking for is IFNULL, look here https://www.w3schools.com/sql/sql_isnull.asp
You are close. You can do:
(CASE WHEN "GROSS_SF" IS NULL OR "GROSS_SF" = 0 THEN 0
ELSE "GROSS_SALES" / "GROSS_SF"
END)
In SQL, divide by zero errors are often avoided using NULLIF():
"GROSS_SALES" / NULLIF("GROSS_SF", 0)
However, that returns NULL rather than 0. If you really want zero:
COALESCE("GROSS_SALES" / NULLIF("GROSS_SF", 0), 0)
This is a bit shorter to write and almost equivalent to your version (this returns 0 if "GROSS_SALES" is NULL, which your version does not).
You can use NULLIF() to prevent arithmetic divide by zero errors :
select . . . ,
GROSS_SALES / nullif(GROSS_SF, 0)
from table t;
However, this would return null instead of error, if you want to display 0 instead then you need to use isnull() (MS SQL Specific) or coalesce() (SQL Standard).
So, you can express it :
select . . . ,
isnull(GROSS_SALES / nullif(GROSS_SF, 0), 0)
from table t;

how to handle divide by zero error in sql

cast(CAST(countAta AS float)
/ CAST(DATEDIFF(day,#searchDate,#EndDate) AS float) as decimal(16,2)
)
You can avoid such situations by setting the following parameters before your query and it should work just fine.
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
This would return a NULL when you do something like this: 123 / 0
The important point is to set these properties back ON once you are done with such operations. This particularly helps when you have complex queries in your Stored procedure and you don't want to end up writing more and more CASE statements to handle such a situation.
You should always use TRY-CATCH block and use the built-in error handling functions provided by SQL. Also, you can handle it in another way --
SELECT CASE
WHEN (CAST(DATEDIFF(Day, #searchDate, #EndDate) AS FLOAT) AS DECIMAL(16, 2)) = 0
THEN NULL -- Ideally it should return NULL but you can change it as per your requirement
ELSE CAST(CAST(Counter AS FLOAT) / CAST(DATEDIFF(Day, #searchDate, #EndDate) AS FLOAT) AS DECIMAL(16, 2))
END
The best way is NULLIF() . . . but you can't turn the value back into a 0:
select CAST(CAST(countAta AS float) /
NULLIF(DATEDIFF(day, #searchDate, #EndDate), 0
) as decimal(16, 2)
)
This returns NULL if the denominator is 0. Note that you don't have to cast to a float twice.
You could use NULLIF to avoid devided by zero error.
It returns NULL when denominator equals 0
CAST(countAta AS decimal(16,2)) /ISNULL(NULLIF(DATEDIFF(day,#searchDate,#EndDate),0), 1)
Or use CASE WHEN
CAST(countAta AS decimal(16,2)) /
CASE WHEN DATEDIFF(day,#searchDate,#EndDate) = 0 THEN 1
ELSE DATEDIFF(day,#searchDate,#EndDate)
END

How to Return a Value using CASE, DECODE, and/or NVL

I'm having a bit of trouble with this. I need a formula that will give me an actual result regardless of whether or not the values are NULL and/or 0. See the following;
SELECT
[...columns...],
(NVL(SUM(table1.qty_rtnd), 0) + NVL(SUM(table1.qty_defective), 0)) / CASE (NVL(table1.sales, 0)) WHEN 0 THEN 1 END AS six_wk_pct_defective,
[...more columns...]
Values in this particular instance:
table1.qty_rtnd = NULL
table1.qty_defective = 7
table1.sales = 560
If the CASE statement is not in this formula and the divisor is 0, Oracle SQL Developer throws an error back to me telling me I cannot divide by zero. That is fine, but when I try to apply a CASE statement to the dividend portion of this formula, the field in the query result is NULL when it should not be (in this particular case, the math makes it that is should be 0.0125).
What am I doing wrong? How can I use CASE, NVL, DECODE or any other functions to fix this issue?
Thanks,
-Ant
UPDATE:
For those looking for an answer. One was provided by someone which is the following;
SELECT (NVL (qty_rtnd, 0) + NVL (qty_defective, 0)) / NVL (NULLIF (sales, 0), 1) FROM table1
How about
SELECT (NVL (qty_rtnd, 0) + NVL (qty_defective, 0)) / NVL (sales, 1) FROM table1
or
SELECT (NVL (qty_rtnd, 0) + NVL (qty_defective, 0)) / NVL (NULLIF (sales, 0), 1) FROM table1
to safeguard sales=0
It's rather hard to understand what you are asking here since you haven't provided us a test case. You haven't told us, for example, what values the various columns have. You told us that, apparently, the desired result is 0.0125 but without any idea what inputs we're supposed to use, we're a bit blind.
If the only problem is your denominator, I suspect that you want the denominator to be
CASE WHEN NVL( table1.sales, 0 ) = 0
THEN 1
ELSE table1.sales
END
If that guess is not correct, please help us out by posting a reproducible test case.

SQL CASE Statement Not Working Correctly

I have a view in SQL Server 2008 with several columns that are expressions of one column divided by another. I have to account for the divisor being 0, so I use a CASE statement. Here is an example of one:
CASE SUM(dbo.GameStats.BringBacksAttempted)
WHEN 0 THEN
0
ELSE
SUM(dbo.GameStats.BringBacks) / SUM(dbo.GameStats.BringBacksAttempted)
END
Even when SUM(BringBacksAttempted) and SUM(BringBacks) are not 0, the statement is always 0. What am I doing wrong?
What data type is BringBacksAttempted and BringBacks?
If both are int and the result comes to be a fraction, you will only see integer part of it.
e.g. 100 / 250 will return 0.
Whereas, CAST(100 as Decimal) / 250 will return 0.40000
Use a CAST or CONVERT on one of the fields.
Try:
CASE
WHEN SUM(dbo.GameStats.BringBacksAttempted) = 0 THEN
0
ELSE
SUM(dbo.GameStats.BringBacks) / SUM(dbo.GameStats.BringBacksAttempted)
END