Get minimum and maximum decimal scale value - sql

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

Related

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

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.

Datatype trouble in SQL Server 2008

I have a data something like this.
70.6
70.60
70.7
70.70
I can't use varchar as I need to perform arithmetic operations (>,< or floor), when I used float all records change to 70.7 and 70.6 from 70.70 and 70.60
When I changed to decimal(2,2), then all 70.6 records changed to 70.60.
Please suggest which data type suits for me.
Business need to retain 70.6 as it is and 70.60 as it is.
Currently data is in dataware house and stored in varchar.
I am preparing data mart and written query like
Result1 = CASE WHEN Dia = '' OR Dia > 28 OR M.Dia < 6 THEN 'Dia' END,
Result2 = CASE WHEN Width = '' OR Width > 16 OR M.Width < 3 THEN 'Width' END,
Result6 = CASE WHEN Bore] = '' OR FLOOR(LOG10(REVERSE(ABS(M.[Center Bore])+1)))+1 <> 2 THEN 'Bore' END,
From the mathematical point of view, there is no difference between 70.6 and 70.60. If your business rules must treat these values as different values, and you want to also be able to perform mathematical operations of them, you should keep them as decimal in your database, and I suggest adding a tinyint column that will specify the number of decimal digits of the original string value.
create a stored procedure that will get the value as string, calculate the number of decimal digits, convert the string to decimal, and save both of these values into the database.
When selecting the value you convert it to string and manipulate the decimal digits as you please.
You can use Convert(float, **) to convert the data from nvarchar.
I don't think there would be any difference can occur when your data is either 60.6 or 60.60 while performing arithmetic operation (>,< or floor)
select convert(float, '60.6') as val
Output: 60.6
as you mentioned in the comment
because I am checking data have only 1 digit after decimal
Then you can form get such a string using charindex and left.
select left(val, charindex('.', val) + 1) as new_val
from (select '60.6666' as val) as x
Input string : 60.6666
Output String : 60.6
now you can use
convert(float, new_val) as val
like,
select convert(float, left(val, charindex('.', val) + 1)) as val
from (select '60.6666' as val) as x

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)

Round off to the smallest integer value

I'm using this query to round off the numbers and this round off the next value. Now I need to round off to the before value means if the value is 45.67 then the value should be 45. I tried these two queries and still I need to tweak the values.
Method1:
parsename('$' + convert(varchar,convert(money,round(sum(Column1 * Column2),0)),1),2)
Method2:
parsename('$' + convert(varchar,convert(money,floor(Column1 * Column2),0),1),2)
Really appreciate any suggestions.
The CEILING function returns the smallest integer greater than or equal to the specified numeric expression. The FLOOR function returns the largest integer less than or equal to the specified numeric expression. For example, in considering a numeric expression of 12.9273, CEILING returns 13 and FLOOR returns 12. The return value of both FLOOR and CEILING has the same data type as the input numeric expression.
SELECT CEILING(12.9273);
Here is the result set.
13
SELECT FLOOR(12.9273);
Here is the result set.
12
http://technet.microsoft.com/en-us/library/ms190927%28v=sql.105%29.aspx
To round down you can use FLOOR()
E.G.
DECLARE #number numeric(5,2)
SET #number = 45.67
SELECT FLOOR(#number)
You'd get the result 45
With your example, it looks like it's already working?
declare #number1 numeric(5,2)
declare #number2 numeric(5,2)
set #number1 = 1.23
set #number2 = 21.69
select parsename('$' + convert(varchar,convert(money,floor(#number1 * #number2),0),1),2)
select #number1 * #number2
Results
$26
26.6787

Truncate (not round) decimal places in SQL Server

I'm trying to determine the best way to truncate or drop extra decimal places in SQL without rounding. For example:
declare #value decimal(18,2)
set #value = 123.456
This will automatically round #value to be 123.46, which is good in most cases. However, for this project, I don't need that. Is there a simple way to truncate the decimals I don't need? I know I can use the left() function and convert back to a decimal. Are there any other ways?
ROUND ( 123.456 , 2 , 1 )
When the third parameter != 0 it truncates rather than rounds.
Syntax
ROUND ( numeric_expression , length [ ,function ] )
Arguments
numeric_expression
Is an expression of the exact numeric or approximate numeric data
type category, except for the bit data type.
length
Is the precision to which numeric_expression is to be rounded. length must be an expression of type tinyint, smallint, or int. When length is a positive number, numeric_expression is rounded to the number of decimal positions specified by length. When length is a negative number, numeric_expression is rounded on the left side of the decimal point, as specified by length.
function
Is the type of operation to perform. function must be tinyint, smallint, or int. When function is omitted or has a value of 0 (default), numeric_expression is rounded. When a value other than 0 is specified, numeric_expression is truncated.
select round(123.456, 2, 1)
SELECT Cast(Round(123.456,2,1) as decimal(18,2))
Here's the way I was able to truncate and not round:
select 100.0019-(100.0019%.001)
returns 100.0010
And your example:
select 123.456-(123.456%.001)
returns 123.450
Now if you want to get rid of the ending zero, simply cast it:
select cast((123.456-(123.456%.001)) as decimal (18,2))
returns 123.45
Actually whatever the third parameter is, 0 or 1 or 2, it will not round your value.
CAST(ROUND(10.0055,2,0) AS NUMERIC(10,2))
Do you want the decimal or not?
If not, use
select ceiling(#value),floor(#value)
If you do it with 0 then do a round:
select round(#value,2)
Another truncate with no rounding solution and example.
Convert 71.950005666 to a single decimal place number (71.9)
1) 71.950005666 * 10.0 = 719.50005666
2) Floor(719.50005666) = 719.0
3) 719.0 / 10.0 = 71.9
select Floor(71.950005666 * 10.0) / 10.0
Round has an optional parameter
Select round(123.456, 2, 1) will = 123.45
Select round(123.456, 2, 0) will = 123.46
ROUND(number, decimals, operation)
number => Required. The number to be rounded
decimals => Required. The number of decimal places to round number to
operation => Optional. If 0, it rounds the result to the number of decimal. If another value than 0, it truncates the result to the number of decimals. Default value is 0
SELECT ROUND(235.415, 2, 1)
will give you 235.410
SELECT ROUND(235.415, 0, 1)
will give you 235.000
But now trimming0 you can use cast
SELECT CAST(ROUND(235.415, 0, 1) AS INT)
will give you 235
This will remove the decimal part of any number
SELECT ROUND(#val,0,1)
SELECT CAST(Value as Decimal(10,2)) FROM TABLE_NAME;
Would give you 2 values after the decimal point. (MS SQL SERVER)
Another way is ODBC TRUNCATE function:
DECLARE #value DECIMAL(18,3) =123.456;
SELECT #value AS val, {fn TRUNCATE(#value, 2)} AS result
LiveDemo
Output:
╔═════════╦═════════╗
║ val ║ result ║
╠═════════╬═════════╣
║ 123,456 ║ 123,450 ║
╚═════════╩═════════╝
Remark:
I recommend using built-in ROUND function with 3rd parameter set to 1.
I know this is pretty late but I don't see it as an answer and have been using this trick for years.
Simply subtract .005 from your value and use Round(#num,2).
Your example:
declare #num decimal(9,5) = 123.456
select round(#num-.005,2)
returns 123.45
It will automatically adjust the rounding to the correct value you are looking for.
By the way, are you recreating the program from the movie Office Space?
Try like this:
SELECT cast(round(123.456,2,1) as decimal(18,2))
If you desire to take some number like 89.0904987 and turn it into 89.09 by simply omitting the undesired decimal places, simply use the following:
select cast(yourColumnName as decimal(18,2))
The following screenshot is from W3Schools SQL Data Types section, which describes what decimal(18,2) is doing:
Therefore,
select cast(89.0904987 as decimal(18,2))
gives you: 89.09
Please try to use this code for converting 3 decimal values after a point into 2 decimal places:
declare #val decimal (8, 2)
select #val = 123.456
select #val = #val
select #val
The output is 123.46
I think you want only the decimal value,
in this case you can use the following:
declare #val decimal (8, 3)
SET #val = 123.456
SELECT #val - ROUND(#val,0,1)
I know this question is really old but nobody used sub-strings to round. This as advantage the ability to round really long numbers (limit of your string in SQL server which is usually 8000 characters):
SUBSTRING('123.456', 1, CHARINDEX('.', '123.456') + 2)
I think we can go much easier with simpler example solution found in Hackerrank:
Problem statement: Query the greatest value of the Northern Latitudes
(LAT_N) from STATION that is less than 137.2345. Truncate your answer
to 4 decimal places.
SELECT TRUNCATE(MAX(LAT_N),4)
FROM STATION
WHERE LAT_N < 137.23453;
Solution Above gives you idea how to simply make value limited to 4 decimal points. If you want to lower or upper the numbers after decimal, just change 4 to whatever you want.
Mod(x,1) is the easiest way I think.
select convert(int,#value)