Error converting varchar to numeric with MSSQL - sql-server

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

Related

Fixing divide by zero error with case statement

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!

Query fails on "converting character string to smalldatetime data type"

I've been tasked with fixing some SQL code that doesn't work. The query reads from a view against a predicate. The query right now looks like so.
SELECT TOP (100) Beginn
FROM V_LLAMA_Seminare
//Removal of the following line makes the query successful, keeping it breaks it
where Beginn > (select cast (getdate() as smalldatetime))
order by Beginn desc
When I run the above query, I am greeted with the following error.
Msg 295, Level 16, State 3, Line 1
Conversion failed when converting character string to smalldatetime data type.
I decided to remove the WHERE clause, and now it runs returning 100 rows.
At first, I thought that behind the scenes, SQL Server was somehow including my predicate when bringing back the View . But then I investigated how the View was being created, especially the Beginn field, and at no point does it return a String.
Long story short, the column that becomes the Beginn field is a BIGINT timestamp like 201604201369.... The original user transforms this BIGINT to a smalldatetime using the following magic.
....
CASE WHEN ma.datum_dt = 0
THEN null
ELSE CONVERT(smalldatetime, SUBSTRING(CAST(ma.datum_dt AS varchar(max)),0,5) + '-' +
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),5,2) + '-' +
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),7,2) + ' ' +
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),9,2) +':'+
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),11,2) +':' +
RIGHT(CAST(ma.datum_dt AS varchar(max)),2)) END AS Beginn
...
My last attempt at finding the problem was to query the view and run the function ISDATE over the Beginn column and see if it returned a 0 which it never did.
So my question is two fold, "Why does a predicate break something" and two "Where on earth is this string error coming from when the Beginn value is being formed from a BIGINT".
Any help is greatly appreciated.
This problem is culture related...
Try this and then change the first SET LANGUAGE to GERMAN
SET LANGUAGE ENGLISH;
DECLARE #bi BIGINT=20160428001600;
SELECT CASE WHEN #bi = 0
THEN null
ELSE CONVERT(datetime, SUBSTRING(CAST(#bi AS varchar(max)),0,5) + '-' +
SUBSTRING(CAST(#bi AS varchar(max)),5,2) + '-' +
SUBSTRING(CAST(#bi AS varchar(max)),7,2) + ' ' +
SUBSTRING(CAST(#bi AS varchar(max)),9,2) +':'+
SUBSTRING(CAST(#bi AS varchar(max)),11,2) +':' +
RIGHT(CAST(#bi AS varchar(max)),2)) END AS Beginn
It is a very bad habit to think, that date values look the same everywhere (Oh no, my small application will never go international ...)
Try to stick to culture independent formats like ODBC or ISO
EDIT
A very easy solution for you actually was to replace the blank with a "T"
SUBSTRING(CAST(ma.datum_dt AS varchar(max)),7,2) + 'T' +
Then it's ISO 8601 and will convert...
The solution was found after looking through #Shnugo's comment. When I took my query which contained the Bigint->Datetime conversion logic, and put it into a CTE with "TOP 100000000" to avoid any implicit conversion actions, my query worked. Here is what my view looks like now with some unimportant parts omitted.
---Important part---
CREATE VIEW [dbo].[V_SomeView] AS
WITH CTE AS (
SELECT TOP 1000000000 ma.id AS MA_ID,
---Important part---
vko.extkey AS ID_VKO,
vko.text AS Verkaufsorganisation,
fi.f7000 AS MDM_Nr,
vf.f7105 AS SAPKdnr,
CASE WHEN ma.datum_dt = 0 --Conversion logic
CASE WHEN ma.endedatum_dt = 0 --Conversion logic
CONVERT(NVARCHAR(MAX),art.text) AS Art,
.....
FROM [ucrm].[dbo].[CRM_MA] ma,
[ucrm].[dbo].[CRM_fi] fi,
[ucrm].[dbo].[CRM_vf] vf,
[ucrm].[dbo].[CRM_ka] vko,
[ucrm].[dbo].[CRM_ka] art,
[ucrm].[dbo].[CRM_ka] kat
where ma.loskz = 0
and fi.loskz = 0
and vf.loskz = 0
and fi.F7029 = 0
and vf.F7023 = 0
...
GROUP BY ma.id,
vko.extkey,
vko.text,
fi.f7000 ,
vf.f7105,
ma.datum_dt,
ma.endedatum_dt,
....
)
select * FROM CTE;

Why is my CASE statement requiring the THEN part to be of data type INT?

I am trying to run a query where the below CASE statement is one of the lines. I'm using Report Builder 3.0.
However, I get an error that says :
Conversion failed when converting the varchar value 'Case 1' to data type int; Microsoft SQL Server, Error: 245".
Why is the CASE statement requiring the THEN part to be an INT data type ?
(CASE
WHEN jobs.Uf_Production_Line = 'LN BM6'
THEN 'Case 1'
ELSE
99999
END
) AS line
When using CASE statement, all result expressions must have the same data type. If not, the result will be converted to the data type with a higher precedence. According to BOL
Returns the highest precedence type from the set of types in
result_expressions and the optional else_result_expression.
And since INT has a higher data type precedence than VARCHAR, your query produces an error:
Conversion failed when converting the varchar value 'Case 1' to data
type int; Microsoft SQL Server, Error: 245".
To fix this, you should convert your ELSE part to VARCHAR.
ELSE '99999'
Because your else uses a value with data type int:
ELSE 99999
You use data types (varchar and int) that can't be exchanged automatically.
An option is to use:
ELSE '99999'
You should use '99999' instead of 99999. All values should be the same datatype in CASE, for now in your ELSE part values is of INT datatype.
Full code should be like:
(CASE WHEN jobs.Uf_Production_Line = 'LN BM6' THEN 'Case 1'
ELSE '99999'
END
) AS line
A case statement can only return one data type. So use the number as varchar:
(CASE WHEN jobs.Uf_Production_Line = 'LN BM6'
THEN 'Case 1'
ELSE '99999'
END
) AS line
OR you can return NULL instead of 9999 if you want to represent it as an invalid value for Line:
(CASE WHEN jobs.Uf_Production_Line = 'LN BM6'
THEN 'Case 1'
ELSE NULL
END
) AS line
Because 99999 is an int. Both cases must return the same data type.

Conversion failed when converting the varchar value in case statement

I cant not get my head around it. We have following simple query.
DECLARE #bFlag bit
SET #bFlag = 0
SELECT something = CASE
WHEN #bFlag = 1 THEN
CASE
WHEN RS.intInterval = 1 THEN '"Days"'
WHEN RS.intInterval = 2 THEN '"Weeks"'
WHEN RS.intInterval = 3 THEN '"Months"'
WHEN RS.intInterval = 4 THEN '"Years"'
END
Else
RS.intInterval
End
from MyTable AS RS WITH (NOLOCK)
So I want to get intInterval(which is int) if flag is not set to true. Otherwise if flag is set to true, I want to get Days, Weeks, etc depending upon value of intInterval. If I run this with #bFalg = 1, I get this error:
Conversion failed when converting the varchar value '"Weeks"' to data
type int
which does not make any sense as I am not converting anything.
I know I can fix it by putting cast (intInterval as varchar) in else part. However I want to know the reason why I am getting this error, why case is trying to convert 'Weeks' to int?
When using CASE statement, all result expressions must have the same data type. If not, the result will be converted to the data type with a higher precedence. According to BOL:
Returns the highest precedence type from the set of types in
result_expressions and the optional else_result_expression.
Since INT has a higher data type precedence than VARCHAR, "Weeks" get converted to INT and that produces the error:
Conversion failed when converting the varchar value '"Weeks"' to data
type int
Another example that will produce the same error:
SELECT CASE WHEN 1 = 1 THEN 'True' ELSE 0 END
The solution is to convert RS.intInterval to VARCHAR:
CONVERT(VARCHAR(10), RS.intInterval)
Your final query should be:
DECLARE #bFlag bit
SET #bFlag = 0
SELECT something = CASE
WHEN #bFlag = 1 THEN
CASE
WHEN RS.intInterval = 1 THEN '"Days"'
WHEN RS.intInterval = 2 THEN '"Weeks"'
WHEN RS.intInterval = 3 THEN '"Months"'
WHEN RS.intInterval = 4 THEN '"Years"'
END
Else
CONVERT(VARCHAR(10), RS.intInterval)
End
from MyTable AS RS WITH (NOLOCK)

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.

Resources