SQL Convert float to comma varchar with decimals - sql

I have a couple floats that are kinda big. They're around a 100 million.
I would like this number to show like the following 123,456,789.01234
I've found that I can use CONVERT if its a money datatype but this doesn't do the full trick (it leaves off some decimal places).
I have to have commas on the left and five decimal places on the right.
Is there any built in SQL function to help with this? Or do I have to write a custom function?
Thanks
*** Update
I forgot to mention that I'm just displaying these as varchars. So there isn't any calculations after this.
This is running on an SQL database so MySQL and Oracle won't work.

DECLARE #f FLOAT
SET #f = 123456789.01234
SELECT LEFT('$' + CONVERT(VARCHAR(20), CAST(#f AS MONEY), 1), LEN(#f) - 2)
this will cut it up to two places of decimal for formatting. You can change LEN(#f) - 2 to modify this setting.

if you are just displaying this as text you can do the following:
oracle :
select to_char(123456789.01234,'999,999,999.99999') from dual; => 123,456,789.01234
MySQL :
select format(123456789.01234,5) => 123,456,789.01234<br>
the MySQL function rounds

Related

SQL get decimal with only 2 places with no round

I have a query (SQL Server) that returns a decimal. I only need 2 decimals without rounding:
In the example above I would need to get: 3381.57
Any clue?
You could accomplish this via the ROUND() function using the length and precision parameters to truncate your value instead of actually rounding it :
SELECT ROUND(3381.5786, 2, 1)
The second parameter of 2 indicates that the value will be rounded to two decimal places and the third precision parameter will indicate if actual rounding or truncation is performed (non-zero values will truncate instead of round).
Example
You can see an interactive example of this in action here.
Another possibility is to use TRUNCATE:
SELECT 3381.5786, {fn TRUNCATE(3381.5786,2)};
LiveDemo
If you want to control the representation, you need to output the value as a string. One method is to convert to a decimal and then to a string:
select cast(cast(total as decimal(10, 2)) as varchar(255))
Another method is to convert to a string using str(). However, this often requires the removal of spaces:
select replace(str(total, 10, 2), ' ', '')

Is this a casting bug in SQL Server 2016 RC0?

Returns 45.2478
SELECT
CAST(
geography::STPointFromText( 'POINT(-81.2545 44.1244)', 4326 ).Lat + 1.12342342
AS VARCHAR(50)
)
Returns 4.524782342440000e+001
SELECT
CONVERT(
VARCHAR(50),
geography::STPointFromText( 'POINT(-81.2545 44.1244)' , 4326 ).Lat + 1.1234234244,
2
)
According to the "Truncating and Rounding Results" section on this page it looks like CAST should never truncate a float but it's doing it in this case.
The link to the docs that you included in the question has an answer.
CAST is the same as CONVERT without explicitly specifying the optional style parameter.
float and real Styles
Value: 0 (default)
Output: A maximum of 6 digits. Use in scientific notation, when appropriate.
So, when you use CAST it is the same as using CONVERT with style=0. Which returns a maximum of 6 digits, i.e. result is rounded to 6 digits.
It is due to the style part you mentioned in CONVERT function
Your query with style = 2
SELECT CONVERT(VARCHAR(50),geography::STPointFromText('POINT(-81.2545 44.1244)',4326).Lat+1.1234234244,2)
Result : 4.524782342440000e+001
But when I remove the Style part from Convert function
SELECT CONVERT(VARCHAR(50),geography::STPointFromText('POINT(-81.2545 44.1244)',4326).Lat+1.1234234244)
Result : 45.2478
which is same as CAST function
FYI, Style 2 is used to format dates in yy.mm.dd format
Quote from you: "it looks like CAST should never truncate a float but it's doing it in this case."
Attention: The example you write here does not use float, but decimal. These are two different types, and it is very important to distinguish between them. decimalhas by default 6 digits, that explains this behaviour.
Everything is in check. SQL Server is one of Microsoft's most stable software pieces, you will hardly find a bug there ;)

How to find values with certain number of decimal places using SQL?

I'm trying to figure out a way, using SQL, to query for values that go out to, say, 5 or more decimal places. In other words, I want to see only results that have 5+ decimal places (e.g. 45.324754) - the numbers before the decimal are irrelevant, however, I still need to see the full number. Is this possible? Any help if appreciated.
Assuming your DBMS supports FLOOR and your datatype conversion model supports this multiplication, you can do this:
SELECT *
FROM Table
WHERE FLOOR(Num*100000)!=Num*100000
This has the advantage of not requiring a conversion to a string datatype.
On SQL Server, you can specify:
SELECT *
FROM Table
WHERE Value <> ROUND(Value,4,1);
For an ANSI method, you can use:
SELECT *
FROM Table
WHERE Value <> CAST(Value*100000.0 AS INT) / 100000.0;
Although this method might cause an overflow if you're working with large numbers.
I imagine most DBMSs have a round function
SELECT *
FROM YourTable
WHERE YourCol <> ROUND(YourCol,4)
This worked for me in SQL Server:
SELECT *
FROM YourTable
WHERE YourValue LIKE '%._____%';
select val
from tablename
where length(substr(val,instr(val, '.')+1)) > 5
This is a way to do it in oracle using substr and instr
You can use below decode statement to identify maximum decimal present in database table
SELECT max(decode(INSTR(val,'.'), 0, 0, LENGTH(SUBSTR(val,INSTR(val,'.')+1)))) max_decimal
FROM tablename A;

How do I count decimal places in SQL?

I have a column X which is full of floats with decimals places ranging from 0 (no decimals) to 6 (maximum). I can count on the fact that there are no floats with greater than 6 decimal places. Given that, how do I make a new column such that it tells me how many digits come after the decimal?
I have seen some threads suggesting that I use CAST to convert the float to a string, then parse the string to count the length of the string that comes after the decimal. Is this the best way to go?
You can use something like this:
declare #v sql_variant
set #v=0.1242311
select SQL_VARIANT_PROPERTY(#v, 'Scale') as Scale
This will return 7.
I tried to make the above query work with a float column but couldn't get it working as expected. It only works with a sql_variant column as you can see here: http://sqlfiddle.com/#!6/5c62c/2
So, I proceeded to find another way and building upon this answer, I got this:
SELECT value,
LEN(
CAST(
CAST(
REVERSE(
CONVERT(VARCHAR(50), value, 128)
) AS float
) AS bigint
)
) as Decimals
FROM Numbers
Here's a SQL Fiddle to test this out: http://sqlfiddle.com/#!6/23d4f/29
To account for that little quirk, here's a modified version that will handle the case when the float value has no decimal part:
SELECT value,
Decimals = CASE Charindex('.', value)
WHEN 0 THEN 0
ELSE
Len (
Cast(
Cast(
Reverse(CONVERT(VARCHAR(50), value, 128)) AS FLOAT
) AS BIGINT
)
)
END
FROM numbers
Here's the accompanying SQL Fiddle: http://sqlfiddle.com/#!6/10d54/11
This thread is also using CAST, but I found the answer interesting:
http://www.sqlservercentral.com/Forums/Topic314390-8-1.aspx
DECLARE #Places INT
SELECT TOP 1000000 #Places = FLOOR(LOG10(REVERSE(ABS(SomeNumber)+1)))+1
FROM dbo.BigTest
and in ORACLE:
SELECT FLOOR(LOG(10,REVERSE(CAST(ABS(.56544)+1 as varchar(50))))) + 1 from DUAL
A float is just representing a real number. There is no meaning to the number of decimal places of a real number. In particular the real number 3 can have six decimal places, 3.000000, it's just that all the decimal places are zero.
You may have a display conversion which is not showing the right most zero values in the decimal.
Note also that the reason there is a maximum of 6 decimal places is that the seventh is imprecise, so the display conversion will not commit to a seventh decimal place value.
Also note that floats are stored in binary, and they actually have binary places to the right of a binary point. The decimal display is an approximation of the binary rational in the float storage which is in turn an approximation of a real number.
So the point is, there really is no sense of how many decimal places a float value has. If you do the conversion to a string (say using the CAST) you could count the decimal places. That really would be the best approach for what you are trying to do.
I answered this before, but I can tell from the comments that it's a little unclear. Over time I found a better way to express this.
Consider pi as
(a) 3.141592653590
This shows pi as 11 decimal places. However this was rounded to 12 decimal places, as pi, to 14 digits is
(b) 3.1415926535897932
A computer or database stores values in binary. For a single precision float, pi would be stored as
(c) 3.141592739105224609375
This is actually rounded up to the closest value that a single precision can store, just as we rounded in (a). The next lowest number a single precision can store is
(d) 3.141592502593994140625
So, when you are trying to count the number of decimal places, you are trying to find how many decimal places, after which all remaining decimals would be zero. However, since the number may need to be rounded to store it, it does not represent the correct value.
Numbers also introduce rounding error as mathematical operations are done, including converting from decimal to binary when inputting the number, and converting from binary to decimal when displaying the value.
You cannot reliably find the number of decimal places a number in a database has, because it is approximated to round it to store in a limited amount of storage. The difference between the real value, or even the exact binary value in the database will be rounded to represent it in decimal. There could always be more decimal digits which are missing from rounding, so you don't know when the zeros would have no more non-zero digits following it.
Solution for Oracle but you got the idea. trunc() removes decimal part in Oracle.
select *
from your_table
where (your_field*1000000 - trunc(your_field*1000000)) <> 0;
The idea of the query: Will there be any decimals left after you multiply by 1 000 000.
Another way I found is
SELECT 1.110000 , LEN(PARSENAME(Cast(1.110000 as float),1)) AS Count_AFTER_DECIMAL
I've noticed that Kshitij Manvelikar's answer has a bug. If there are no decimal places, instead of returning 0, it returns the total number of characters in the number.
So improving upon it:
Case When (SomeNumber = Cast(SomeNumber As Integer)) Then 0 Else LEN(PARSENAME(Cast(SomeNumber as float),1)) End
Here's another Oracle example. As I always warn non-Oracle users before they start screaming at me and downvoting etc... the SUBSTRING and INSTRING are ANSI SQL standard functions and can be used in any SQL. The Dual table can be replaced with any other table or created. Here's the link to SQL SERVER blog whre i copied dual table code from: http://blog.sqlauthority.com/2010/07/20/sql-server-select-from-dual-dual-equivalent/
CREATE TABLE DUAL
(
DUMMY VARCHAR(1)
)
GO
INSERT INTO DUAL (DUMMY)
VALUES ('X')
GO
The length after dot or decimal place is returned by this query.
The str can be converted to_number(str) if required. You can also get the length of the string before dot-decimal place - change code to LENGTH(SUBSTR(str, 1, dot_pos))-1 and remove +1 in INSTR part:
SELECT str, LENGTH(SUBSTR(str, dot_pos)) str_length_after_dot FROM
(
SELECT '000.000789' as str
, INSTR('000.000789', '.')+1 dot_pos
FROM dual
)
/
SQL>
STR STR_LENGTH_AFTER_DOT
----------------------------------
000.000789 6
You already have answers and examples about casting etc...
This question asks of regular SQL, but I needed a solution for SQLite. SQLite has neither a log10 function, nor a reverse string function builtin, so most of the answers here don't work. My solution is similar to Art's answer, and as a matter of fact, similar to what phan describes in the question body. It works by converting the floating point value (in SQLite, a "REAL" value) to text, and then counting the caracters after a decimal point.
For a column named "Column" from a table named "Table", the following query will produce a the count of each row's decimal places:
select
length(
substr(
cast(Column as text),
instr(cast(Column as text), '.')+1
)
) as "Column-precision" from "Table";
The code will cast the column as text, then get the index of a period (.) in the text, and fetch the substring from that point on to the end of the text. Then, it calculates the length of the result.
Remember to limit 100 if you don't want it to run for the entire table!
It's not a perfect solution; for example, it considers "10.0" as having 1 decimal place, even if it's only a 0. However, this is actually what I needed, so it wasn't a concern to me.
Hopefully this is useful to someone :)
Probably doesn't work well for floats, but I used this approach as a quick and dirty way to find number of significant decimal places in a decimal type in SQL Server. Last parameter of round function if not 0 indicates to truncate rather than round.
CASE
WHEN col = round(col, 1, 1) THEN 1
WHEN col = round(col, 2, 1) THEN 2
WHEN col = round(col, 3, 1) THEN 3
...
ELSE null END

Sybase convert issue from float to varchar

First, I need to mention that my current sybase db version is Adaptive Server Enterprise 12.5.4. I aim to convert float data type into varchar via sybase convert function in order to concat several of these kinds of variables, format and store in string type.
Unfortunately, it is not the case. Simply using convert(varchar(20), float_var) or cast() function cannot correctly return the precise value.
For example, ...
declare #float_var float
begin
select #float_var =345.1237 --from table actually
select convert(varchar(20),#float_var) --return 345.1236999999
end
The incorrect string results returned occasionally have 99999 or 00001 suffix.
I tried many function including specify the precision, but there are still several cases not working on it. The sybase internal function does not exactly work on it.
I suppose this is a gerneral issue while using Sybase DB, however few answer found in serach. During my past experience, Sybase store procedure gammer always has sort of tolerance in runtime and internal fix when error encounter. This issue make me confused how Sybase works internally. Any advice would be appreciated, thanks in advance.
there are a couple of possible solutions for this.
firstly, let's try to convert the float to decimal first, then to varchar.
select cast(cast(#float_var as decimal(13,4)) as varchar)
alternatively, and this is where my ASE memory might fail me a little, would be to use the STR function like so:
Select ltrim(str(#float_var, 25, 5))
You have to TRIM the output as the STR function padding empty spaces on to the left of the result
this works for me:
declare #float_var float
begin
select #float_var = 96.332
select cast(cast(#float_var as decimal(13,4)) as varchar) -- Returns 96.3320
end
declare #float_var float
begin
select #float_var = 345.1237
select cast(cast(#float_var as decimal(13,4)) as varchar) -- Returns 345.1237
end