SQL Server: Calculate length before decimal places - sql-server

I want to calculate the length of a values in a numeric column. The values are randomly as
255.0125 , 28847.0125 etc
I need the length of values before the decimal places only. So far the first value it should be 3, for second value it should be 5.
What SQL function can be helpful here.

I suggest using FLOOR function, add ABS as well if numbers can be negative:
SELECT LEN(FLOOR(9.99999))
SELECT LEN(FLOOR(ABS(-9.99999)))
This will fail
SELECT LEN(cast(-9.99999 as int))--Result 2
SELECT LEN(FLOOR(-9.99999))--Result 3

Try:
select len(cast(999999999.99999 as int))
select len(cast(28847.0125 as int))
Or
select len(cast('28847.0125' as decimal))
Or
select len(round('28847.0125', 0, 1))
Or
EDIT 2 suggestion by deepanshu-kalra
:
SELECT LEN(FLOOR(9.99999))

Use ROUND() function, which will convert decimal to int, then use LEN()
query will be
select LEN(ROUND('255.0125', 0))
ROUND() function systax :
ROUND(value,decimalPlace)

Related

Way to show items where more than 5 decimal places occur?

I am trying to filter out some query results to where it only shows items with 6 decimal places. I don't need it to round up or add 0's to the answer, just filter out anything that is 5 decimal places or below. My current query looks like this: (ex. if item is 199.54215 i dont want to see it but if it is 145.253146 i need it returned)
select
TRA_CODPLANTA,
TRA_WO,
TRA_IMASTER,
tra_codtipotransaccion,
tra_Correlativo,
TRA_INGRESOFECHA,
abs(tra_cantidadparcial) as QTY
from mw_tra_transaccion
where FLOOR (Tra_cantidadparcial*100000) !=tra_cantidadparcial*100000
and substring(tra_imaster,1,2) not in ('CP','SG','PI','MR')
and TRA_CODPLANTA not in ('4Q' , '5C' , '5V' , '8H' , '7W' , 'BD', 'DP')
AND tra_INGRESOFECHA > #from_date
and abs(tra_cantidadparcial) > 0.00000
Any assistance would be greatly appreciated!
Here is an example with ROUND, which seems to be the ideal function to use, since it remains in the realms of numbers. If you have at most 5 decimal places, then rounding to 5 decimal places will leave the value unchanged.
create table #test (Tra_cantidadparcial decimal(20,10));
INSERT #test (Tra_cantidadparcial) VALUES (1),(99999.999999), (1.000001), (45.000001), (45.00001);
SELECT * FROM #test WHERE ROUND(Tra_cantidadparcial,5) != Tra_cantidadparcial;
drop table #test
If your database values are VARCHAR and exist in the DB like so:
100.123456
100.1
100.100
You can achieve this using a wildcard LIKE statement example
WHERE YOUR_COLUMN_NAME LIKE '%.[0-9][0-9][0-9][0-9][0-9][0-9]%'
This will being anything containing a decimal place followed by AT LEAST 6 numeric values
Here is an example using a conversion to varchar and using the LEN - the CHARINDEX of the decimal point, I'm not saying this is the best way, but you did ask for an example in syntax, so here you go:
--Temp Decimal value holding up to 10 decimal places and 10 whole number places
DECLARE #temp DECIMAL(20, 10) = 123.4565432135
--LEN returns an integer number of characters in the converted varchar
--CHARINDEX returns the integer location of the decimal where it is found in the varchar
--IF the number of characters left after subtracting the index of the decimal from the length of the varchar is greater than 5,
--you have more than 6 decimal places
IF LEN(CAST(#temp AS varchar(20))) - CHARINDEX('.', CAST(#temp AS varchar(20)), 0) > 5
SELECT 1
ELSE
SELECT 0
Here is a shorthand way.
WHERE (LEN(CONVERT(DOUBLE PRECISION, FieldName % 1)) - 2) >=5
One way would be to convert / cast that column to a lower precision. Doing this would cause automatic rounding, but that would show you if it is 6 decimals or not based on the last digit. If the last digit of the converted value is 0, then it's false, otherwise it's true.
declare #table table (v decimal(11,10))
insert into #table
values
(1.123456789),
(1.123456),
(1.123),
(1.123405678)
select
v
,cast(v as decimal(11,5)) --here, we are changing the value to have a precision of 5. Notice the rounding.
,right(cast(v as decimal(11,5)),1) --this is taking the last digit. If it's 0, we don't want it
from #table
Thus, your where clause would simply be.
where right(cast(tra_cantidadparcial as decimal(11,5)),1) > 0

How can I convert a float into int using the 'round' method in SQL Server?

I tried with
select ROUND(1235.53)
--(It can contain "n" digit of scale)
But I got this error:
The round function requires 2 to 3 arguments.
I am not sure what is the use of other parameters.
Set decimals to zero
select cast(ROUND(1235.53,0) as int) Returns 1236
select cast(1235.53 as int) Returns 1235
Better to use CAST INT/CEILING/FLOOR:
SELECT CEILING(1235.53)
SELECT FLOOR(1235.53)
SELECT CAST(1235.53 AS INT)
CEILING: Gives you the upper bound integer value
FLOOR: Gives you the lower bound integer value
Here is another approach that just formats the result into the desired format:
SELECT FORMAT(ROUND(1235.53,0), 'N0')
'N' stands for numerical format and the digit behind it controls the number of decimal points.

How to limit decimal values based on condition in SQL Server

I have an amount field which is decimal(13,5) in SQl Server.
So it takes values like 22.23456 (5 values after decimals)
Now i want to limit the decimal places based on condition like below:
for 22.23456, result should be 22.24
for 22.20001, result should be 22.21
for 22.20000, result should be 22.20
for 22.00000, result should be 22.00
So if there is any number other than 0 after 2nd decimal place(in 1st ex:4),just increase the value 2nd decimal value by 1.(22.2345 to 22.24)
Is there any function or do we need to use length type functions to achieve this?
Please help.
Thanks in advance.
Since you want the highest value in the hundredths position using standard rounding will not work. You can however use a little math and CEILING to accomplish.
with MyValues(SomeValue) as
(
select 22.23456 union all
select 22.20001 union all
select 22.20000 union all
select 22.00000
)
select cast(ceiling(SomeValue * 100) / 100. as numeric(9,2)) as MyResult
from MyValues
https://msdn.microsoft.com/en-us/library/ms189818.aspx

How to use ROUNDDOWN in sqlserver

I want to use ROUNDDOWN function.
When i tried using the following query,it gives me an error saying "'rounddown' is not a recognized built-in function name."
select rounddown(25.227,2)
My requirement is to rounddown the value to two decimals
for ex: for value 25.22789 result should be 25.22
and round up also
for ex: for value 25.22789 result should be 25.23
Any help?
Thanks in advance
Use third parameter of ROUND() function to truncate and then CONVERT() it to DECIMAL(x, 2) to get rid of unwanted trailing zeros.
Fiddle demo
SELECT CONVERT(DECIMAL(10,2), ROUND(25.227, 2, 1)) RoundDown,
CONVERT(DECIMAL(10,2), ROUND(25.227, 2, 0)) RoundUp
Results
| RoundDown | RoundUp |
|-----------|---------|
| 25.22 | 25.23 |
I think you are looking for either CEILING() or floor() function like
select CEILING(25.227) //results in 26
(OR)
select FLOOR(25.227) //Results in 25
EDIT:
for ex: for value 25.22789 result should be 25.22
You can try like below
select round(25.22789, 2, 2)
Which will result in 25.22000
ROUND FUNCTION
You can use SELECT ROUND(#num, 2, 1)
As per ROUND description:
ROUND ( numeric_expression , length [ ,function ] )
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.
RESULT
25.22
CHARINDEX and LEFT
Alternatively you can use CHARINDEX and LEFT in following if you want to do "ROUND DOWN" and use simple ROUND to do "ROUND UP"
DECLARE #num DECIMAL(16,3) = 25.227
SELECT LEFT(#num,CHARINDEX('.',#num)+2) as [RoundDown],
ROUND(#num,2) as [RoundUp]
RESULT
RoundDown RoundUp
25.22 25.23
UPDATE
As per comments about ROUNDUP you can use in following:
SELECT ROUND(22.22289 + 0.005, 2) as [RoundUp1]
RESULT
25.23
DEMO
You can test it at SQL FIDDLE
For rounding down, just use some simple math (one decimal place farther than you want to round to):
SELECT ROUND(25.22789 - 0.005, 2)
OUTPUT 25.22
For rounding up, simply use ROUND:
SELECT ROUND(22.22789, 2)
OUTPUT 25.23
Also you can use CAST:
declare #num decimal(18,5) = 22.22719
select #num, CAST(#num as decimal(18,3))
Greetings from the future.
Multiply it up, divide it back down?
declare #myroundednumber numeric(9,4)=25.227
select 'Original' version,#myroundednumber figure
select 'Rounded Up',cast(ceiling(25.227 *100)/100 as decimal(9,2))
select 'Rounded Down',cast(floor(25.227 *100)/100 as decimal(9,2))

How to get the count of digits after the decimal point in a float column in ms sql?

I have to count the digits after the decimal point in a database hosted by a MS Sql Server (2005 or 2008 does not matter), in order to correct some errors made by users.
I have the same problem on an Oracle database, but there things are less complicated.
Bottom line is on Oracle the select is:
select length( substr(to_char(MY_FIELD), instr(to_char(MY_FILED),'.',1,1)+1, length(to_char(MY_FILED)))) as digits_length
from MY_TABLE
where the filed My_filed is float(38).
On Ms Sql server I try to use:
select LEN(SUBSTRING(CAST(MY_FIELD AS VARCHAR), CHARINDEX('.',CAST(MY_FILED AS VARCHAR),1)+1, LEN(CAST(MY_FIELD AS VARCHAR)))) as digits_length
from MY_TABLE
The problem is that on MS Sql Server, when i cast MY_FIELD as varchar the float number is truncated by only 2 decimals and the count of the digits is wrong.
Can someone give me any hints?
Best regards.
SELECT
LEN(CAST(REVERSE(SUBSTRING(STR(MY_FIELD, 13, 11), CHARINDEX('.', STR(MY_FIELD, 13, 11)) + 1, 20)) AS decimal))
from TABLE
I have received from my friend a very simple solution which is just great. So I will post the workaround in order to help others in the same position as me.
First, make function:
create FUNCTION dbo.countDigits(#A float) RETURNS tinyint AS
BEGIN
declare #R tinyint
IF #A IS NULL
RETURN NULL
set #R = 0
while #A - str(#A, 18 + #R, #r) <> 0
begin
SET #R = #R + 1
end
RETURN #R
END
GO
Second:
select MY_FIELD,
dbo.countDigits(MY_FIELD)
from MY_TABLE
Using the function will get you the exact number of digits after the decimal point.
The first thing is to switch to using CONVERT rather than CAST. The difference is, with CONVERT, you can specify a format code. CAST uses whatever the default format code is:
When expression is float or real, style can be one of the values shown in the following table. Other values are processed as 0.
None of the formats are particularly appealing, but I think the best for you to use would be 2. So it would be:
CONVERT(varchar(25),MY_FIELD,2)
This will, unfortunately, give you the value in scientific notation and always with 16 digits e.g. 1.234567890123456e+000. To get the number of "real" digits, you need to split this number apart, work out the number of digits in the decimal portion, and offset it by the number provided in the exponent.
And, of course, insert usual caveats/warnings about trying to talk about digits when dealing with a number which has a defined binary representation. The number of "digits" of a particular float may vary depending on how it was calculated.
I'm not sure about speed. etc or the elegance of this code. it was for some ad-hoc testing to find the first decimal value . but this code could be changed to loop through all the decimals and find the last time a value was greater than zero easily.
DECLARE #NoOfDecimals int = 0
Declare #ROUNDINGPRECISION numeric(32,16) = -.00001000
select #ROUNDINGPRECISION = ABS(#ROUNDINGPRECISION)
select #ROUNDINGPRECISION = #ROUNDINGPRECISION - floor(#ROUNDINGPRECISION)
while #ROUNDINGPRECISION < 1
Begin
select #NoOfDecimals = #NoOfDecimals +1
select #ROUNDINGPRECISION = #ROUNDINGPRECISION * 10
end;
select #NoOfDecimals

Resources