Converting this varchar to a decimal with the appropriate decimal point? - sql-server-2005

I've been playing with cast()s and such with this and can't seem to get things to work. I have a varchar string that's 18 characters long that I'd like to convert or cast to a decimal, with five decimal places. So for instance, this string:
00000001987600130
Would become 19876.00130
It's the case that I'll always have a 17 character string, with the last five characters reserved as the decimal place.
I've been playing with casts and converts but I'm not quite there. For instance, these statements get me (sort of) close but not exactly.
select CAST('00000001987600130' as bigint)/100000.0
select (convert(decimal(17,5),left('00000001987600130',12),0))
If you have a suggestion I'm happy to try it. Thanks!

This works fine for me:
SELECT CONVERT (decimal, '00000001987600130') / 100000
The reason why the first one didnt work is because the result of the CAST is an integer, and dividing an integer by 100000 rounds / truncates it (not sure which) so that it is still an integer.

To ensure you get what you want do a final CAST to ensure decimal(17,5) exactly
SELECT CAST((CAST('00000001987600130' AS decimal) / 100000) AS decimal(17,5))
Otherwise, the output type is not correct in scale or precision and may have effects later.

Related

PostgreSQL- Round REAL data type (yes, I know numeric exist)

I know REAL data type is not accurate and normally for currency I should use numeric data type.
But, I'm asked to do some stuff and one of the conditions is that the data type is real.
When I try to do round((....),2) for example, I get that round function does not exist for this data type.
My question is, without converting, is there any function that can return a REAL value rounded to 0?
Many thanks!1
As you can see here it's no way to round without any type cast. It's only two kinds of function exists:
round(dp or numeric) - round to nearest integer
round(v numeric, s int) - round to s decimal places
Real = double precision. So you need to use convert anyway if you want to get some decimal places:
select round('123.456789'::real::numeric,2)
upd. Keep care about rounding+cast at big real numbers:
select round('12122156.567'::real::numeric, 2); --< rounding up to 6 digits, result = 12122200
select round('12122156.567'::real::DOUBLE PRECISION::numeric,2); --<< rounding result = 12122157
Or you can use round without decimal places:
select round('123.456789'::real)
round a numeric value to 0 after the dot?
ROUND(numeric_value, 0)
After investigation, converting to ::numeric is the only way around

Trying to calculate the difference in punch-in/punch-out times without rounding

I need to get a total of hours worked but my result always ends up in a rounded number. I need to show the real hours worked to two decimal places. Here is my code thus far:
CAST((datediff(mi,CONVERT(datetime,p.Punchin,114),CONVERT(datetime,p.Punchout,114)) - datediff(mi,CONVERT(datetime,p.Lunch_in,114),CONVERT(datetime,p.Lunch_out,114)))/60 AS decimal (12,2)) AS "Hours Worked"
Not sure where I am going wrong but assistance is greatly appreciated.
This is happening because of data type precedence. Since you're working with both integers on both sides of the expression, it's being implicitly converted to INT. Try diving by "60.00" or "CAST(60 AS DECIMAL(12,2))".
https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-ver15
Looks like you're getting the total number of minutes (an integer) and then dividing by 60 (an integer). Dividing an integer by an integer is integer division and will result in an integer with the fractional part dropped. THEN you're casting that integer to a decimal(12,2) but the fractional part is already gone.
Try changing /60 to /60.0 to avoid the integer division. I think that should fix it for you.
You can find more discussion of integer division in SQL server in these posts:
Integer division in sql server
How to get a float result by dividing two integer values using T-SQL?

SQL Round cast to float

I have a problem with round in SQL Server 2014: when I round a number to 2 decimal places sometimes the rounded number is different if I cast to float before or not.
For example, if I execute:
select round(cast(3.945 as float),2)
select round(3.945,2)
I have:
3.94
3.950
But if I execute:
select round(cast(3.935 as float),2)
select round(3.935,2)
I have:
3.94
3.940
It seems incorrect, rounding 3.935 and 3.945 casting to float before, I obtain the same value. Is this a bug?
The problem here is that float is a binary floating point type, where the representation is an approximation of the value. Floats do not losslessly convert to or from base 10, because there is no power of 10 that is also a power of 2. So when this is converted it is done in a way that leaves a roundoff error that pushes the value just before the rounding threshold.
Oddly I cannot reproduce the same behaviour on PostgreSQL and I am not entirely sure why (it may be that on PostgreSQL, round takes a numeric value and this forces a conversion back).
Never use floats where absolute accuracy is required. This occurs not only in databases, but in almost every programming language as well.
As #ChrisTravers says in his answer the issue with rounding a float is that you're not getting exact arithmetic. i.e. That explains why round(3.945,2) rounds up to 3.95 whilst round(3.945E0,2) effectively rounds down to 3.94.
If you're wondering why you see more than 2 decimal places in some cases, that's because of the type you're dealing with. i.e. 3.94 is a float, so doesn't have a specified number of decimal places; whilst 3.950 is the result of rounding a decimal(4,3); which even though we've rounded to 2 decimal places doesn't affect the precision of the type (i.e. it's still decimal(4,3); not converted to decimal(4,2) or decimal(3,2)).
If the purpose of this rounding is for display purposes, you're best of using the str function. i.e.
select str(3.945,4,2) --decimal
select str(3.945E0,4,2) --float
In the above the 4 is the length of the string (i.e. includes the decimal point as a character), and the 2 is the number of decimal places to show.
NB: In this scenario you're chaning the data type to varchar(4).
The below code allows you to see what type you get after performing an operation:
declare #result sql_variant = str(3.945E0,4,2)
select sql_variant_property(#result, 'BaseType') [BaseType]
,sql_variant_property(#result, 'MaxLength') [MaxLength]
,sql_variant_property(#result, 'Precision') [Precision]
,sql_variant_property(#result, 'Scale') [Scale]

to_number function in sql

i could not understand why following code
SQL>
Select to_number('1234.64', '9999.9') from Dual;
returns this number 1234.6?is it something like rounding ,truncation or?please help me to understand this code,i know to_number functions,i have used many times this code for simple chars,but here it is not clear anything
This looks a lot like Oracle, but I suspect that the result would be similar in any SQL that used to_number.
The to_number function takes two arguments: the string to be converted to a number, and the format string for the conversion.
In the example, '12345.64' is the string to be converted, while '9999.9' is the format string. In this format string, a 9 stands for a digit while a . stands for the decimal point.
So the function is asking to convert the string '12345.64' to a number with up to 4 digits to the right of the decimal point, and only 1 digit after the decimal point.
The second argument is optional - under normal circumstances, I would omit it.
You should use
SELECT to_number('1234.64', '9999.99') from Dual;
Your mask tells engine you want just one decimal, so number gets rounded.
If you want to get exact number, don't specify any mask:
SELECT to_number('1234.64') from Dual;

Wrong value when casting a float(24)value to float(53) in SQL 2005

I am running this sql code in SQL 2005
declare #a as float(24)
set #a=0.85
select cast ( #a as float(53))
and the result is
0.850000023841858
does anyone know why?
Thanks.
The first seven digits are the default level of precision for a float when in the declaration float(N) the value of N is 24 or less. After that, the digits could show up as pretty much anything when cast to a float of greater precision. That's the 'floating point'.
http://msdn.microsoft.com/en-us/library/ms173773.aspx
The number you see is as close as the computer can get within however many binary digits it has available to use.
If you try and write 1/3 in decimal, but you only have enough space for 8 digits, the closest you can get is 0.33333333. That's still off by a quite a way, but if you had more decimal places you could get more accurate. This is exactly the same probably as the computer faces, but whereas each of your successive digits represents 1/10ths, 1/100ths, 1/1000ths, the computer works in 1/2, 1/4, 1/8, 1/16.