Attempting to determine decimals places using CHARINDEX, getting: Error converting data type varchar to float - sql

I use this piece of code all the time on many objects when trying to determine the number of decimals after the '.'. The target system I am moving data to can only handle 2 d.p. So we I find data with >2 d.p. I multiply by 10, 100, 1000 and also multiply the 'price per' field value by the same factor.
SELECT
HQPROD, [HQPR1],
Decimals = CASE Charindex('.', [HQPR1])
WHEN 0 THEN 0
ELSE LEN(CAST(CAST(REVERSE(CONVERT(VARCHAR(50), [HQPR1], 128)) AS FLOAT) AS BIGINT))
END
FROM
[SM_REP].[dbo].[BPCSF64_HQT]) EDP ON P.HQPROD = EDP.HQPROD
The column datatype I am working with is DECIMAL(15,5).
Sample data:
HQPROD HQPR1
--------------------------
47001-RM64 175.89900
47001-T06OX 5.84500
47002-20T 80.44700
47002-T24 98.10300
47002-T32 144.07000
47003-01 1.54000
47003-02 1.54000
47003-03 0.51000
Error message:
Error converting data type varchar to float.

SELECT
HQPR1,
Decimals =
CASE WHEN HQPR1 > 0 THEN
CASE Charindex('.', [HQPR1])
WHEN 0 THEN 0
ELSE LEN(CAST(CAST(REVERSE(CONVERT(VARCHAR(50), [HQPR1], 128)) AS FLOAT) AS BIGINT))
END
ELSE
CASE Charindex('.', [HQPR1])
WHEN 0 THEN 0
ELSE LEN(CAST(CAST(REVERSE( Stuff((CONVERT(VARCHAR(50), [HQPR1], 128)),1,1,'' )) AS FLOAT) AS BIGINT))
END
END
This will work also for negative numbers, which as sticky bit said,could be causing your error.

Related

T-SQL :: Error converting data type varchar to numeric when changing 1 to 0.5

I'm writing a complex T-SQL query with CASE that will help me calculate how much time it will take me to migrate databases based on the size of each database:
SELECT
ProductVersion
,CompatibilityLevel
,convert(numeric(10,2), substring([Size], 1, (len([Size]) - 3))) as [Size in MB]
,CASE
when ProductVersion < '11%' THEN 1
when ProductVersion = NULL then 1
ELSE ''
END +
CASE
when CompatibilityLevel < '110' then 1
when CompatibilityLevel = NULL then 1
ELSE ''
END +
CASE
when convert(numeric(10,2), substring([Size], 1, (len([Size]) - 3))) < 100.00 THEN 1 -- Here is the problem
ELSE ''
END AS [Hours of work]
FROM MyDatabaseList
All good, it works when I set 1 hour of work for every database which has less then 100.00 MB.
Also all other values are summed and in the Hours of work column you can see numbers like 0, 1, 3, 2...
This means SQL Server is calculating values. All good.
But well, telling to my manager that I have to work 1 hour for a database that only has 100.00 MB of size is ridiculous.
Let's change the line:
when convert(numeric(10,2), substring([Size], 1, (len([Size]) - 3))) < 100.00 THEN 1
and let's put 0.5 instead of 1:
when convert(numeric(10,2), substring([Size], 1, (len([Size]) - 3))) < 100.00 THEN 0.5
...and bang - I get this error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
Questions:
Why this error now?
Why it was successfully calculating before and now needs a datatype somewhere?
What change do I have to add to my query?
Why it says on Line 1? The error must be on Line 16, right?
The error is telling you the conversion is happening in the statement that starts in line 1.
As for why, it's because '' cannot be converted to a numeric but it can be converted to an int.
SELECT CONVERT(decimal(2,1),'')
--Error converting data type varchar to numeric.
GO
SELECT CONVERT(int,'')
--
GO
You were previously converting it to an int (the literal 1 is an int). Get out of the habit of declaring '' for a number; it is by definition not a number, it is a zero length string. If you want zero, then use 0.

even after converting it to varchar it is giving error: Error converting data type varchar to float,

SELECT a.[Emp_No],
a.[Emp_Name],
a.[Band],
b.[Max_Exp] AS Max_Yrs_Experience,
CASE WHEN a.Performance_Score = 0 AND (a.Status_Active > 0 OR a.Status_New > 0)
THEN CONVERT(varchar, 0)
WHEN a.Performance_Score > 0
THEN [Performance_Score]
ELSE 'No History Data Found'
END AS Performance_Score
INTO #EXPER
FROM #PERFORMANCE a, #agg_exp b
WHERE a.[Emp_No] = b.[Emp_No]
ORDER BY Performance_Score DESC
Error converting varchar to float.
I don't know why I am getting this error.
The difficulty you are having is due to that SQL Server requires that all posssible values generated in a CASE expression have the same type. Since your ELSE uses text, which can't be converted to any numeric type, the only option is to convert the numbers to text.
CASE WHEN a.Performance_Score = 0 AND (a.Status_Active > 0 OR a.Status_New > 0)
THEN CONVERT (VARCHAR(10), 0) -- zero as text
WHEN a.Performance_Score > 0
THEN CONVERT (VARCHAR(10), [Performance_Score]) -- performance score as text
ELSE 'No History Data Found' -- this is already text
END AS Performance_Score
Going by the error message, I am assuming here that [Performance Score] is a float column. If it be some other type, you would have to modify the call to CONVERT() appropriately.

Get minimum and maximum decimal scale value

I have float datatype column in sql server and I need to get minimum decimal scale and maximum decimal scale .
Here is SQL Fiddle
I am using
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), value, 128)
) AS FLOAT) AS BIGINT))
Which work great but when value is something in negative eg -0.061 it throw error Error converting data type varchar to float.
So for alter I search and found that there is function name PARSENAME(#var,1) which is working perfect for negative numbers too but this function returns after decimal value and return type is nchar
Eg : If float value is -0.061 its will return 061 of return type nchar So i can not use len function to get its length.
SO how do I make this working either by using fiddle or by using above function.
Try using the ABS() function
SELECT value,
Decimals = CASE Charindex('.', value)
WHEN 0 THEN 0
ELSE
Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ABS(value), 128)
) AS FLOAT) AS BIGINT))
END
FROM numbers
I guess using ABS() function should be enough. Shouldn't it?
A mathematical function that returns the absolute (positive) value of
the specified numeric expression.
SELECT value
, Decimals = CASE CHARINDEX('.', value)
WHEN 0 THEN 0
ELSE LEN(CAST(CAST(REVERSE(CONVERT(VARCHAR(50), ABS(value), 128)) AS FLOAT) AS BIGINT))
END
FROM numbers;
This will work.
Just replace simple value with -value when it is negative i.e
CASE WHEN value<0 THEN -value ELSE value END
SELECT value,
Decimals = CASE WHEN Charindex('.', value)=0
THEN 0
ELSE Len (Cast(Cast(Reverse(CONVERT(VARCHAR(50), ABS(value), 128) ) AS FLOAT) AS BIGINT))
END
FROM numbers
To remove - symbol, use ABS function. ABS(value) in place of value

How do i check that in 100.00 number after decimal point is greater than 0 or not?

Actually I want to know that if number is 0.75 then consider it as value and if number is 75.00 then consider it as percentage and if number is 12.25 then also consider it as value
Modulus when divided by one will divide out the entire whole section and leave only the decimal remainder. try following:
SELECT CASE (100.00 % 1) WHEN 0 THEN 'Percent' ELSE 'Value' END
SELECT CASE (0.75 % 1) WHEN 0 THEN 'Percent' ELSE 'Value' END
One method is to convert to an integer and see if the original value matches. Your question is unclear on what you want the output to be, but perhaps:
select (case when value between 0 and 1 then 'value'
when cast(value as int) = value then 'percentage'
else 'value'
end)
Note: this is potentially not perfect because of inaccuracies in using floating point representations. It should work for decimal representations. Note also that 12.00001 is treated as a value rather than a percentage. Your question is quite unclear on what to do in this case. Most floating point representations store low-valued integers exactly, so this will work for exact matches.
If you only care about the first two decimal places, you can use the str() function or a double cast. For instance, for positive values:
select (case when value between 0 and 1 then 'value'
when right(str(value - floor(value as int), 10, 2), 2) = '00' then 'percentage'
else 'value'
end)

SQL Server: casting the column datatype

SQL Server 2005/ 2008
I have kept a CASE condition for a SQL query which results Float /Numeric Value. One of the CASE condition is to say N/A. I kept the piece of code.
For column : Compliance - Possible values could be N/A,100.0,99.1 ... ( nvarchar, float ).
select
x.MemberName, x.DOB, x.FilePath,
x.Medication, x.NDC, x.Directions,
x.Name, x.Strength, x.GenericName,
x.QtyOrdered, x.DaysSupply, x.DateFilled,
CASE WHEN x.test = 0 THEN 'N/A'
WHEN compliance > 100.0 THEN '100.0'
ELSE CAST(FLOOR(compliance * 10)/10.0 AS DECIMAL(3, 1))
END AS [Compliance]
Above syntax spills error as ..
Msg 8114, Level 16, State 5, Line 10
Error converting data type varchar to numeric.
How should I type cast the field ?
CASE is an expression that returns a single result and regardless of the path it always needs to result in the same data type (or implicitly convertible to the same data type). Try:
...
CASE
WHEN x.test = 0 THEN 'N/A'
WHEN compliance > 100.0 THEN '100.0'
ELSE CONVERT(VARCHAR(5), CAST(FLOOR(compliance *10)/10.0 AS DECIMAL(3,1)))
END AS as [Compliance];
You're not consistent in your CASE statement - you need to provide the same data type as result for all options.
CASE WHEN x.test = 0 THEN 'N/A'
WHEN compliance > 100.0 THEN '100.0'
ELSE CAST(FLOOR(compliance * 10)/10.0 AS DECIMAL(3, 1))
END AS [Compliance]
Since the first two options return a string ('N/A' or '100.0'), your last option also must return a string value:
CASE WHEN x.test = 0 THEN 'N/A'
WHEN compliance > 100.0 THEN '100.0'
ELSE CAST(CAST(FLOOR(compliance * 10)/10.0 AS DECIMAL(3, 1)) AS VARCHAR(20))
END AS [Compliance]