SQL Server: Convert FLOAT to NVARCHAR, maximum accuracy, without scientific notation - sql

Without using scientific notation, I need to convert a FLOAT to a string, without showing scientific notation, and capturing all possible precision.
For example, when I execute SELECT 1E0 / 1346E0 I get the following result:
This is how SQL Server displays a FLOAT value by default.
In this case, it displays 18 decimal places, which is more than the STR function can provide.
It also does not add any trailing zeros.
If SQL Server Management Studio can do this, can I also get this conversion in my code?
I need to avoid scientific notation at all costs, even if there are 20 leading zeros after the decimal point. A long string is not a problem.
Unfortunately, the CONVERT function does not provide what I need, even with style 3

try format()
SELECT
1E0 / 1346E0
, format(1E0 / 1346E0,'N18')

declare #float float = 0.000742942050520059
select cast(cast(#Float as decimal(38,35)) as varchar(200))
As was also noted, format works too, although I'm not a huge fan of it as it's a kind of heavy hitting CLR. but for one offs, it's fine.

Related

Truncation using round function isn't achieved as expected in sql server

I have a field stored in float datatype. I need to convert it to numeric without it getting implicitly rounded in the process of conversion.
I have tried round(float_data,scale,1). Seems to work fine for most of the cases.but when the number of digits after decimal places is less than scale mentioned in round function it tries to floor down the number rather than appending 0 at the end.
For instance, round (0.0243,5,1) returns 0.02429. Why isn't it simply truncating the number to the number of digits mentioned?
I know this issue is when we use float as source datatype but I cannot change the source datatype.
The same truncation happens right when the same is achieved via ssis. Is there any way in sql to achieve this?
Because when converted to a float, the decimal 0.0243 is stored as 0.02429999969899654388427734375, which truncates to 0.02429. Looks like you want to round instead of truncate, eg
declare #f float = 0.0243
select round(#f,5,0)

Unexpected results with double casting numeric datatype in SQL Server

I recently came across a weird case in an ETL process where the results seem unpredictable to me. I read Difference between numeric, float and decimal in SQL Server, but I don't think it's an overflow or decimal precision issue.
Scenario:
Source table "test" in SQL Server 2008 SP3, column a declared as numeric (38,6).
The result is cast first to real, and then to int. The issue doesn't occur if there is a direct cast from numeric to int.
Results of:
SELECT a,CAST(a as real) as real_a,CAST(CAST(a as real) as int) as int_a FROM test;
a: 778881838.810000
real_a: 7.78819E+08
int_a: 778881856
The same experiment, run in SQL Server 2017 (sql fiddle) gives this:
http://sqlfiddle.com/#!18/45aca/2
a: 778881838.81
real_a: 778881860
int_a: 778881856
I can (vaguely) understand the ..19E+08 case, but why is there a +18 difference in the double conversion case? The number seems completely arbitrary to me.
OK, first of all, the result in SQL Server 2017 for real_a is not 778881860. It is 778881856, exactly, just as in SQL Server 2008. How this floating-point value is presented by the client is another matter -- Management Studio shows me 7.788819E+08, sqlcmd produces 7.7888186E+8, and apparently SQL Fiddle uses another library altogether (one I would personally have issue with, seeing as how it obscures significant figures!)
This value is not arbitrary. REAL is a single-precision floating point type that cannot represent 778881838.81 exactly. The closest representable value is 778881856, hence your result (the next lower representable value is 778881792). Without casting to INT, you can see this value using
SELECT STR(CONVERT(REAL, CONVERT(NUMERIC(38, 6), 778881838.810000)), 40, 16)
778881856.0000000000000000
Your use of the term "double" makes me think you're confusing this with FLOAT, which is the double-precision floating point type. FLOAT cannot represent this value exactly either, but it comes much closer:
SELECT STR(CONVERT(FLOAT, CONVERT(NUMERIC(38, 6), 778881838.810000)), 40, 16)
778881838.8099999400000000
Converting this value to an INT yields the (truncated) 778881838. (This truncation is documented and does not happen for conversions to NUMERIC; you'll need to ROUND first before converting if you'd prefer 778881839 instead.)
Easy example for other people that want to test locally:
DECLARE #test numeric (38,6)='778881838.810000'
SELECT #test as [Original],CAST(#test as real) as real_a,CAST(CAST(#test as real) as int) as int_a;
Original real_a int_a
778881838.810000 7.788819E+08 778881856
You would likely need someone from Microsoft to explain the way it works inside the SQL engine (and certainly to know why they made that decision), but I'll take a stab at the reasoning:
If the output is in scientific notation on the first cast and is then needed to cast to an int, it sets the int to the minimum value that would result in that scientific notation. It ends in 6 instead of 5 because rounding on 5 does not consistently round up on all cases (Alternating tie-breaking for example).
But, no matter the reason, if precision is important, you should explicitly cast to a numeric data type with a defined precision.
When you want to convert from float or real to character data, using the STR string function is usually more useful than CAST( ). This is because STR enables more control over formatting. For more information, see STR (Transact-SQL) and Functions (Transact-SQL).
Please find the below links
USE STR Instead of real
STR example
Use the below query : -
SELECT a,STR(a ,38,6) as real_a,CAST(CAST(a as real) as int) as int_a FROM test;
Please let me know if you find any issue.

float or double precision

When I tell postgreSQL to show a column as float, I always get as a result "double precision".
Is it the same?
Like Damien quoted from the documentation:
PostgreSQL also supports the SQL-standard notations float and float(p) for specifying inexact numeric types.
Here, p specifies the minimum acceptable precision in binary digits.
PostgreSQL accepts float(1) to float(24) as selecting the real type,
while float(25) to float(53) select double precision.
Values of p outside the allowed range draw an error.
float with no precision specified is taken to mean double precision.
PostgreSQL, like other databases, supports the SQL standard by supplying an appropriate data type when a certain SQL standard type is requested. Since real or double precision fit the bill here, they are taken instead of creating new redundant types.
The disadvantage is that the data type of a column may read different from what you requested, but as long as it handles your data the way it should, is that a problem?

sql rounding value

I have been successful at rounding my value to one decimal point, but I would like to trim off the multitude of trailing zeros. For example, this:
ROUND(SUM(Duration),1)
...ends up giving me:
16.9000000000000000
how do I trim all those trailing zeros.
mssql
The round function rounds the number, but it leaves the data type unchanged:
ROUND(3.14,1) --> 3.10
By casting a number to numeric(x,1), you both round it and change it's data type to single digit precision:
CAST(3.14 as numeric(6,1)) --> 3.1
For your query, such a cast could look like:
select cast(sum(duration) as numeric(6,1))
But the eventual display format depends on the client. SQL Server Management Studio will display numeric(x,1) with one digit behind the dot, but it is free to display it in another way. Formatting a number is best done client side, outside of SQL.
Use:
CONVERT(Decimal(9, 1), ROUND(SUM(duration), 1))
The second parameter of the DECIMAL data type is the precision - 1 will give you a single digit after the decimal point.

How Decimal places are converted using FLOAT in SQL Server 2000/2005/2008

in this SO question the OP wanted to drop the 0's in the decimal places for his results. Now the example I gave (below) to get around this was to CAST with DECIMAL, then CAST with FLOAT.
e.g.
SELECT CAST(0.55 AS FLOAT)
Using the example above and running it in SQL Server 2005/2008 would seem to bring up the correct result of 0.55. But as Peter in the other post pointed out, running it in SQL Server 2000 produces 0.55000000000000004.
So my questions are:
Is FLOAT to be avoided at all cost when it comes to data conversion in SQL?
Why does cast(0.55 as float) yields 0.55000000000000004 in SQL2k yet 0.55 in later edtions?
Has Microsoft made using FLOAT more reliable in later versions of SQL Server?
Thanks for your time.
My personnal golden rule is: avoid float. I can't remember myself using float in recent years.
All business scenarios I took recenty I had to store currency values, or even numbers with a fixed precision, so I prefer to use DECIMAL or MONEY.