Length of a float as a string - sql

I have a table with a float type column. Most values are like 5.67 but there are some weird ones like 5.44567999999999995
How can I count how many weird ones do I have? What do I have to change in the 2nd select, to give me the result as the 3rd select?
declare #a as float
set #a = 5.44567999999999995
select #a
select LEN(CONVERT(VARCHAR(50), ISNULL(#a, 0)))
select LEN('5.44567999999999995')

If you're just trying to find the "weird" ones and aren't really interested in the length of the values per se, then you might use the ROUND() function instead:
SELECT * FROM myTable
WHERE myValue != ROUND(myValue, 2);
Here "2" is the number of places after the decimal - this should find values that have 3 or more decimal places.
Hope this helps.

Related

SQL/MariaDB SELECT * FROM ... WHERE decimal number

I am having an issue with the SELECT statement. I want to do this:
SELECT * FROM `table1` WHERE x=0.0509
but it returns no rows. I know for sure that there is a row with an x value of 0.0509. If I do:
SELECT * FROM `table1` WHERE x=0
It does in fact return all rows where x=0, this means that my sql statement overall is correct. How do I SELECT where x is a number with decimals? I assume that the decimals is causing the issue?
maybe try balancing the search term between 2 values like this:
SELECT * FROM table1 WHERE x BETWEEN 0 AND 0.1;
This worked for me :)
Photo here
Edit: I can't find any way to get the precise decimal but you can probably just do this but make the values:
SELECT * FROM table1 WHERE x BETWEEN 0.05089999 AND 0.05090001;
This is probably your best way to do it, I'm pretty sure
The FLOAT is an approximate value. So, the stored value is not exactly 0.0509. You should use DECIMAL instead.
You can always convert the value to DECIMAL.
SELECT *
FROM table1
WHERE cast(x as decimal(10,4))=0.0509

How to multiply string value to longint in SQL

I have the below data which I want to multiply together, column A times column B to get column C.
A has datatype string and B has datatype long.
A B
16% 894
15% 200
I have tried this expression in query cast(A as int)*B but it is giving me an error.
You can try below way -
select cast(left(A, patindex('%[^0-9]%', A+'.') - 1) as int)*B
from tablename
You need to remove the '%' symbol before attempting your cast. And assuming you are actually wanting to calculate the percentage, then you also need to divide by 100.00.
cast(replace(A,'%','') as int)/100.00*B
Note: You need to use 100.00 rather than 100 to force decimal arithmetic instead of integer. Or you could cast as decimal(9,2) instead of int - either way ensures you get an accurate result.
You may well want to reduce the number of decimal points returned, in which case cast it back to your desired datatype e.g.
cast(cast(replace(A,'%','') as int)/100.00*# as decimal(9,2))
Note: decimal(9,2) is just an example - you would use whatever precision and scale you need.
The syntax of the cast in SQL Server is CAST(expression AS TYPE);
As you cannot convert '%' to an integer so you have to replace that with an empty character
as below:
SELECT cast(replace(A,'%','') AS int);
Finally you can write as below:
SELECT (cast(replace(A,'%','') AS int)/100.00)*B as C;

SQL server 'like' against a float field produces inconsistent results

I am using LIKE to return matching numeric results against a float field. It seems that once there are more than 4 digits to the left of the decimal, values that match my search item on the right side of the decimal are not returned. Here's an example illustrating the situation:
CREATE TABLE number_like_test (
num [FLOAT] NULL
)
INSERT INTO number_like_test (num) VALUES (1234.56)
INSERT INTO number_like_test (num) VALUES (3457.68)
INSERT INTO number_like_test (num) VALUES (13457.68)
INSERT INTO number_like_test (num) VALUES (1234.76)
INSERT INTO number_like_test (num) VALUES (23456.78)
SELECT num FROM number_like_test
WHERE num LIKE '%68%'
That query does not return the record with the value of 12357.68, but it does return the record with the value of 3457.68. Also running the query with 78 instead of 68 does not return the 23456.78 record, but using 76 returns the 1234.76 record.
So to get to the question: why having a larger number causes these results to change? How can I change my query to get the expected results?
The like operator requires a string as a left-hand value. According to the documentation, a conversion from float to varchar can use several styles:
Value Output
0 (default) A maximum of 6 digits. Use in scientific notation, when appropriate.
1 Always 8 digits. Always use in scientific notation.
2 Always 16 digits. Always use in scientific notation.
The default style will work fine for the six digits in 3457.68, but not for the seven digits in 13457.68. To use 16 digits instead of 6, you could use convert and specify style 2. Style 2 represents a number like 3.457680000000000e+003. But that wouldn't work for the first two digits, and you get an unexpected +003 exponent for free.
The best approach is probably a conversion from float to decimal. That conversion allows you to specify the scale and precision. Using scale 20 and precision 10, the float is represented as 3457.6800000000:
where convert(decimal(20,10), num) like '%68%'
When you are comparing number with LIKE it is implicitly converted to string and then matched
The problem here is that float number is not precise and when it is converted you can get
13457.679999999999999 instead of 13457.68
So to avid this explicitly format number in appropriate format(not sure how to do this in sql server, but it will be something like)
SELECT num FROM number_like_test
WHERE Format("0.##",num) LIKE '%68%'
The conversion to string is rounding your values. Both CONVERT and CAST have the same behavior.
SELECT cast(num as nvarchar(50)) as s
FROM number_like_test
Or
SELECT convert(nvarchar(50), num) as s
FROM number_like_test
provide the results:
1234.56
3457.68
13457.7
1234.76
23456.8
You'll have to use the STR function and correct format parameters to try to get your results. For example,
SELECT STR(num, 10, 2) as s
FROM number_like_test
gives:
1234.56
3457.68
13457.68
1234.76
23456.78
Pretty well solved already, but you only need to CAST once, not twice like the other answer suggests, LIKE takes care of the string conversion:
SELECT *
FROM number_like_test
WHERE CAST(num AS DECIMAL(12,6)) LIKE '%68%'
And here's a SQL Fiddle showing the rounding behavior: SQL Fiddle
It's probably because a FLOAT data type represents a floating point number which is an approximation of the number and should not be relied on for exact comparisons.
If you need to do a search that includes the float value you would need to either store it in a decimal data type (which will hold the exact number) or convert it to a varchar using something like the STR() function

Arithmetic overflow converting numeric (19,16) to data type numeric (19,19)

Trying to do something pretty trivial (convert a column of type numeric(19, 16) to numeric(19, 19), but keep getting an Arithmetic overflow error.
ALTER TABLE X
ALTER COLUMN Column1 numeric(19,19)
Any ideas?
You have data that can't fit in a numeric(19,19) - how you want to "fix" this is up to you - but you need to review the data that won't fit and decide how to deal with it.
If all of the data fitted, it would run fine:
create table X (Column1 numeric(19,16))
create table Y (Column1 numeric(19,16))
insert into X(Column1) values (0.1)
insert into Y(Column1) values (1.0)
This works:
ALTER TABLE X
ALTER COLUMN Column1 numeric(19,19)
This produces the error:
ALTER TABLE Y
ALTER COLUMN Column1 numeric(19,19)
Because you can't put a number with any integral portion into a numeric(19,19).
If you want to find the values that won't fit the changed column definition, run this first:
SELECT * FROM X where ABS(Column1) >= 1.0;
NUMERIC(19,19) means you have 19 digits, and all 19 of them behind decimal point - so your largest number that can be stored is 0.9999999999999999999 (19 9s behind 0.)
So, if in your NUMERIC (19,16) column have any values that are larger or equal then 1 - it will fail to convert it to (19,19).
NUMERIC (19,16) can store three digits left of decimal place and 16 behind it -making 999.9999999999999999 largest possible number.
In exapmle, this will work:
DECLARE #a NUMERIC(19,16)
SET #a = 0.1234567890123456
SELECT CAST (#a AS NUMERIC(19,19))
and this will not:
DECLARE #b NUMERIC(19,16)
SET #b = 123.1234567890123456
SELECT CAST (#b AS NUMERIC(19,19))
nor this:
SELECT CAST (1 AS NUMERIC(19,19))
EDIT: Damien_The_Unbeliever has posted a nice select to check for rows that can't fit into (19,19) you should use it if you really want to convert to NUMERIC (19,1) - but, my guess is you don't really want to convert to (19,19) but rather keep your data and just add 3 digits of precision - which is NUMERIC(22,19)

Find non-integer values in a float field

I'm having trouble finding a way to write a query that will return all non-integers in a float column in SQL Server 2005/8.
I have a float field where the majority of the data in it is actually integers, but I'd like to take a look at the rows where the values actually contain a decimal value. The first thing I tried was modulus 1, but the % operator doesn't work on float values.
Thanks for your help!
I don't know exact syntax of MSSQL, however you could try something like that (pseudo-code)
SELECT ... FROM tbl_name WHERE col_name != CAST(col_name AS INTEGER)
are you just wanting the rows with a decimal in it?
select field
from table
where field like '%.%'
Try something like:
SELECT *
FROM MyTable
WHERE (CONVERT(INT, floatField) - floatField) <> 0
You may also try this:
SELECT * FROM tbl WHERE col != ROUND(col)