Fixing divide by zero error with case statement - sql-server

I have inherited some code with a divide by zero error.
I keep getting the error and not sure if it is the code or where I am placing it.
Should this line be added or replace a line?
Tried adding and replacing with this case statement:
CASE WHEN SUM(PREOP_MME) = 0 THEN 0 ELSE SUM(PREOP_MME) / SUM(COUNT_CASES) END AS PREOP_MME).
SELECT
PROCEDURE_NM
,SUM(PreOp_MME) / SUM(COUNT_CASES) PreOp_MME
,SUM(IntraOp_MME) / SUM(COUNT_CASES) IntraOp_MME
,SUM(PostOp_MME / PostOp_LOS) PostOp_MME
,SUM(Discharge_MME) / SUM(COUNT_CASES) Discharge_MME
,SUM(TOTAL_OVERALL_MME) / SUM(COUNT_CASES) Overall_MME
FROM (
SELECT DISTINCT
Spine.LOG_ID
,Spine.SERV_AREA_ID [Service Area ID]
,Spine.LOC_ID [Revenue Location ID]
,Spine.PRIMARY_PHYS_ID [Provider ID]
,Spine.SURGERY_DATE
,Spine.COUNT_CASES
,Spine.PROCEDURE_NM
,Spine.PostOp_LOS
,(PreOp.SUM_SIG * PreOp.PreOp_MME) AS PreOp_MME
,(IntraOp.SUM_SIG * IntraOp.IntraOp_MME) AS IntraOp_MME
,(PostOp.SUM_SIG * PostOp.PACU_MME) AS PostOp_MME
,DischMeds.DOSE_MME AS Discharge_MME
,(PreOp.SUM_SIG * PreOp.PreOp_MME) +
(IntraOp.SUM_SIG * IntraOp.IntraOp_MME) +
(PostOp.SUM_SIG * PostOp.PACU_MME) + DischMeds.DOSE_MME as TOTAL_OVERALL

You should check for the divisor ( denominator) and not for the divided (numerator) is not equal to 0 so for the first column you coudl try
SELECT
PROCEDURE_NM,
case when SUM(COUNT_CASES) = 0
then 0
else SUM(PreOp_MME)/ SUM(COUNT_CASES) end PreOp_MME,
.....

Just use COALESCE
Here I build a small demo as example
SELECT id,
SUM(`value1`) / SUM(`value2`) as _before,
COALESCE (SUM(`value1`) / SUM(`value2`) , 0) as _after
FROM Table1
GROUP by id;

Thank you for your answers.
I used the CASE WHEN SUM(FIELD) = 0 THEN 0 ELSE SUM(FIELD) / SUM(FIELD) END AS
My error was because I was not accounting for zeros in each instance, only the first. Must be time to go home!

Related

Fix 'Incorrect syntax near the keyword 'WHEN'' error in SQL Server?

I'm trying to implement this two when condition in the case expression but it is just not happening. Please help me fix this?
SELECT
BR, CID, TRNDATE,
CASE
WHEN TRNTYPE = '108' THEN -1 ELSE 1 * TrnAmt/100
WHEN TRNTYPE = '114' THEN (TrnIntAmt - TrnTaxAmt)/100
END as TransactionAmount
FROM
T_TRNHIST
Query Must be like that
SELECT BR, CID, TRNDATE,
CASE
WHEN TRNTYPE = '108' THEN -1
WHEN TRNTYPE = '114' THEN (TrnIntAmt - TrnTaxAmt)/100
ELSE 1 * TrnAmt/100
END as TransactionAmount
FROM T_TRNHIST
Else condition would come at last once all when done
just a little change, move the ELSE to before the END
SELECT BR, CID, TRNDATE,
CASE
WHEN TRNTYPE = '108' THEN -1
WHEN TRNTYPE = '114' THEN (TrnIntAmt - TrnTaxAmt)/100
else 1 * TrnAmt/100
END as TransactionAmount
FROM T_TRNHIST

I'm writing a TSQL procedure and have a query that extracts data . However it's returning the divide by zero error exception

Divide by zero error exception from the below code though I have used ISNULL in my code. Any suggestions on how to fix this.
SELECT
dd.detail_id DETAIL_ID, dd.period_id PERIOD_ID, noff.FGA_ID FGA_ID,
noff.fulfillment_center FULFILLMENT_CENTER, noff.DEMAND_TYPE DEMAND_TYPE,
noff.LEGACY_SSC LEGACY_SSC,
noff.net_offset_forecast NET_OFFSET_FORECAST,
noff.forecast_to_be_consumed FORECAST_TO_BE_CONSUMED,
CASE
WHEN ISNULL(dd.DEPOT_WISE_FORECAST, 0) = 0
THEN 0
ELSE (noff.net_offset_forecast * dd.detail_depot_wise_forecast) / ISNULL((dd.agg_depot_wise_forecast), 0))
END detail_forecast_consumption,
CASE
WHEN ISNULL(dd.DEPOT_WISE_FORECAST, 0) = 0
THEN 0
ELSE (noff.FORECAST_TO_BE_CONSUMED * dd.detail_depot_wise_forecast) / ISNULL((dd.agg_depot_wise_forecast), 0))
END detail_forecast_sales
INTO
aggregate_to_detail_forecast_consumption
FROM
net_offset_forecast noff
JOIN
disaggregate_data dd ON noff.fga_id = dd.snop_item
AND noff.fulfillment_center = dd.fulfillment_center
SELECT
dd.detail_id DETAIL_ID, dd.period_id PERIOD_ID, noff.FGA_ID FGA_ID,
noff.fulfillment_center FULFILLMENT_CENTER,
noff.DEMAND_TYPE DEMAND_TYPE, noff.LEGACY_SSC LEGACY_SSC,
noff.net_offset_forecast NET_OFFSET_FORECAST,
noff.forecast_to_be_consumed FORECAST_TO_BE_CONSUMED,
CASE
WHEN ISNULL(dd.DEPOT_WISE_FORECAST, 0) = 0
THEN 0
ELSE (noff.net_offset_forecast * dd.detail_depot_wise_forecast) / ISNULL((dd.agg_depot_wise_forecast), 0))
END detail_forecast_consumption,
CASE
WHEN ISNULL(dd.DEPOT_WISE_FORECAST, 0) = 0
THEN 0
ELSE (noff.FORECAST_TO_BE_CONSUMED * dd.detail_depot_wise_forecast) / ISNULL((dd.agg_depot_wise_forecast), 0))
END detail_forecast_sales
INTO
aggregate_to_detail_forecast_consumption
FROM
net_offset_forecast noff
JOIN
disaggregate_data dd ON noff.fga_id = dd.snop_item
AND noff.fulfillment_center = dd.fulfillment_center
There should be No divide by zero exception with the above code
You don't want / ISNULL(dd.agg_depot_wise_forecast, 0).
This will return either dd.agg_depot_wise_forecast or 0, depending on whether the first argument is NULL.
You want to use NULLIF(): / NULLIF(dd.agg_depot_wise_forecast, 0).
This will replace zero values with NULL, avoiding the error.
You should check the value and do not attempt top divide when it is NULL. When it is NULL, you are replacing it with 0 and causing a divide by zero error.
Here is a sample:
declare #sample table (id int identity, v1 decimal(10,2), v2 decimal(10,2) null);
insert into #sample (v1, v2) values
(10,2),
(10,null);
--select *, v1/isnull(v2,0)
--from #sample;
select *, case when v2 is null then 0 else v1/v2 end as MyVal
from #sample;
Commented part is how you do it and would error.
Kindly replace your case statement with below corrected case statement.
Changes:
ISNULL((dd.agg_depot_wise_forecast),0) -> ISNULL(NULLIF(dd.agg_depot_wise_forecast,0), 1)
NULLIF() will replace 0 value with NULL value, so ISNULL() will always take 1 from second argument.
CASE WHEN ISNULL(dd.DEPOT_WISE_FORECAST, 0) = 0 THEN 0 ELSE (noff.net_offset_forecast * dd.detail_depot_wise_forecast) / ISNULL(NULLIF(dd.agg_depot_wise_forecast,0), 1)) END detail_forecast_consumption, CASE WHEN ISNULL(dd.DEPOT_WISE_FORECAST, 0) = 0 THEN 0 ELSE (noff.FORECAST_TO_BE_CONSUMED * dd.detail_depot_wise_forecast) / ISNULL(NULLIF(dd.agg_depot_wise_forecast,0), 1)) END detail_forecast_sales

Error: A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations

When i run the following query, an error occurred saying:
A SELECT statement that assigns a value to a variable must not be
combined with data-retrieval operations.
How should I fix this?
Here is the query:
DECLARE #loanInstallmet float
SELECT TOP (1)
loan.loanID,members.offno AS OfficialNumber,
loan.loanAmount,
loan.interestRate,
loan.NoOfInstallment,
loanHistory.presentInstallmentNo,
loanHistory.dateBalanceUpdate,
(loanHistory.presentInstallmentNo + 1) AS InstallmentNo,
members.monthllyContribution AS MonthlyContribution,
#loanInstallmet =
CASE
WHEN loan.remarks = 'Half' THEN ROUND(loanHistory.balanceAmount/ (loan.NoOfInstallment-loanHistory.presentInstallmentNo ), 0)
ELSE ROUND((loan.loanAmount / loan.NoOfInstallment), 0)
END,
CASE
WHEN loanHistory.presentInstallmentNo % 12 = 0 THEN ROUND(((loan.loanAmount-loanHistory.balanceAmount) * loan.interestRate / 1200), 0)
ELSE ROUND((loan.loanAmount * loan.interestRate / 1200), 0)
END AS MonthlyInterest,
LEFT(DATENAME(MONTH,Getdate()),3)as recMonth,
year(GETDATE())as recYear,
loan.isRecovered as LoanIsRecovered,
members.memberIsActive,
loanHistory.status,
ROUND((loanHistory.balanceAmount-#loanInstallmet), 0) AS BalanceAmount,
loan.remarks
FROM loan
INNER JOIN members
ON loan.offNo = members.offno
INNER JOIN loanHistory
ON members.offno = loanHistory.offNo
AND loan.loanID = loanHistory.loanID
WHERE
loan.isRecovered = 0
AND members.memberIsActive = 1
order by loanHistory.presentInstallmentNo DESC
It is saying what it means ! ;)
You can't do:
SELECT TOP (1) loan.loanID,members.offno AS OfficialNumber, ....
at the same time as:
SELECT #loanInstallmet = CASE WHEN loan.remarks = 'Half' THEN
You are either retrieving data for your application, or you are setting the value of a variable. It's not logical to do both at the same time.
If you want to calculate #loanInstallmet and use it in future calculations you can do something like the following:
With tblLoanInstallCalc as (
SELECT TOP (1) loan.loanID,members.offno AS OfficialNumber,loan.loanAmount,loan.interestRate,loan.NoOfInstallment,loanHistory.presentInstallmentNo,loanHistory.dateBalanceUpdate,(loanHistory.presentInstallmentNo + 1) AS InstallmentNo, members.monthllyContribution AS MonthlyContribution,
CASE WHEN loan.remarks = 'Half' THEN ROUND(loanHistory.balanceAmount/ (loan.NoOfInstallment-loanHistory.presentInstallmentNo ), 0) ELSE ROUND((loan.loanAmount / loan.NoOfInstallment), 0) END AS loanInstallmet,
CASE WHEN loanHistory.presentInstallmentNo%12 = 0 THEN ROUND(((loan.loanAmount-loanHistory.balanceAmount) * loan.interestRate / 1200), 0) ELSE ROUND((loan.loanAmount * loan.interestRate / 1200), 0) END AS MonthlyInterest,
LEFT(DATENAME(MONTH,Getdate()),3)as recMonth,year(GETDATE())as recYear ,loan.isRecovered as LoanIsRecovered, members.memberIsActive, loanHistory.status, loan.remarks
FROM loan INNER JOIN
members ON loan.offNo = members.offno INNER JOIN
loanHistory ON members.offno = loanHistory.offNo AND loan.loanID = loanHistory.loanID
WHERE (loan.isRecovered = 0) AND (members.memberIsActive = 1)
)
Select *, ROUND((balanceAmount-loanInstallmet), 0) AS BalanceAmount
From tblLoanInstallCalc
tblLoanInstallCalc is a common table expression (CTE) and is pre-calculating the prerequisites before you try to add up the balance

how to handle Zero divided by zero in sqlserver

how we can handle 0/0 in SQL Server? I used select nullif(0)/nullif(0) but ..
Msg 8134, Level 16, State 1, Line 1 Divide by zero error encountered.
Use NULLIF like this something like this
SELECT 0/NULLIF(0,0)
If you want the result as 0 when you encounter NULL, then use ISNULL/COALESCE
SELECT COALESCE(0/NULLIF(0,0),0)
In your query, you only need to move the ISNULL to check like this isnull(([Total Collection]) / nullif([Billed Amount], 0), 0)
update generalRegionWise set [Collection %] =
convert(VARCHAR,convert(MONEY,100.0 * isnull(([Total Collection]) / nullif([Billed Amount], 0), 0)),1) + '%'
It is recommended to specify the length when converting to VARCHAR like this convert(VARCHAR(50),... In your case it will take the default length of 30.
here are a few more examples.
DECLARE #numerator Int = 0
DECLARE #denominator Int = 0
SELECT ISNULL(NULLIF(#numerator, #denominator),0) AS Result;
SELECT CASE WHEN #denominator = 0
THEN 0
ELSE #numerator / #denominator
END AS Results
Hope this helps.

Error converting varchar to numeric with MSSQL

Query
SELECT TOP 1000
CASE WHEN VRI.Square_Footage <> ''
THEN VRI.Square_Footage
ELSE
CASE WHEN VRI.Property_Type = 'LAND'
THEN CAST((CONVERT(NUMERIC(38, 3),VRI.Acres)*43560) AS DECIMAL)
ELSE
VRI.Lot_Size
END
END
FROM View_Report_Information_Tables AS VRI
Even if I checked for VRI.Acres with isnumeric(), it still yield the same exact error? How can I fix this problem?
ISNUMERIC doesn't guarantee that it will successfully cast to decimal.
SELECT ISNUMERIC('£100') /*Returns 1*/
SELECT CONVERT(NUMERIC(38, 3),'£100') /*Error*/
Additionally all branches of the case statement need to return compatible datatypes. It looks like VRI.Square_Footage is a string.
Does this work for you?
SELECT TOP 1000 CASE
WHEN ISNUMERIC(VRI.Square_Footage + 'e0') = 1 THEN
VRI.Square_Footage
WHEN VRI.Property_Type = 'LAND'
AND ISNUMERIC(VRI.Acres + 'e0') = 1 THEN CAST((
CONVERT(NUMERIC(38, 3), VRI.Acres) * 43560 ) AS DECIMAL)
WHEN ISNUMERIC(VRI.Lot_Size + 'e0') = 1 THEN VRI.Lot_Size
END
FROM View_Report_Information_Tables AS VRI
Here run this
SELECT ISNUMERIC('d25')
That can be converted to float but not decimal/numeric
SELECT CONVERT(FLOAT,'2d5')
As you can see, you can't depend on numeric for decimal/numeric data types
Take a look at IsNumeric, IsInt, IsNumber for some code that will show you how you can check

Resources