Oracle double conversion - sql

I have this example:
CREATE TABLE test
(
VALUE NUMBER (5, 2)
);
INSERT INTO test
VALUES (6.3);
SELECT * FROM test;
In table test, I have a value of 6.3.
I have an application in .NET who queries this table and returns a single value of 6.3.
Assuming the value is stored in the s variable like this:
Dim s As Single = 6.3
Dim d As Double = CDbl(s)
.NET converts the single into a double, and the variable d has this value: 6.3000001907348633. I understand that is a different representation of the 6.3 value, but when I'm using this d value in a operation like this:
(795407.2 * d) / 100 = 50110,6551171188
in PL\SQL when I'm querying the table, I want to get the 6.3000001907348633 value instead of 6.3.
How can I convert this, or there is a datatype that does that? I've tried the BINARY_FLOAT and DOUBLE PRECISION types, but they don't convert this.
EDIT: Using 6.3 value I get: (795407.2 * d) / 100 = 50110,6536. if I round the value to get two decimal places (and assuming that this is a monetary value, I get 50110,66€ and 50110,65€ respectively).

Try using the BINARY_FLOAT Data Type in your SQL.
It represents a 32-bit floating point number in Oracle:
SQL> select cast(6.3 as BINARY_FLOAT) num,
2 to_char(cast(6.3 as BINARY_FLOAT),'0.00000000') num_to_char
3 from dual;
NUM NUM_TO_CHAR
---------- -----------
6,3E+000 6.30000019
Edit:
Sorry, I was too fast and didn't read all your trials
For compatibility purposes, try convert your number / literal to BINARY_FLOAT and then to BINARY_DOUBLE:
SQL> select TO_CHAR(cast(cast(6.3 as BINARY_FLOAT) as BINARY_DOUBLE),'0.000000000000000000') MyNum from dual;
MYNUM
---------------------
6.300000190734863300

Related

postgres round by variable decimal place

I have a rounding length value by contract. I would like to round my data table by this value however I cannot find how to input it dynamically (ie changing 2 in the example below by 5). Is it possible?
Table trading.data18 structure
idcontract integer
close double
Table contracts structure
idcontract integer
rounding double
My static query so far
select ROUND(CAST(close AS numeric),2) from trading.data18 limit 10;
You can use contracts.rounding as a second argument of round.
select round(d.close, c.rounding::integer)::numeric
from trading.data18 as d
join contracts as c using(idcontract);
using(idcontract) is a shorthand for on c.idcontract = d.idcontract

Using decimal in a SQL query

I have a column Amount defined in my SQL Server database as varchar(20), null.
It has values like this:
1.56867
2.0
2.0000
2
If the user in the client app enters 2 for search, then I need to pull all records from the db except value 1.56867.
So search results should yield:
2.0
2.0000
2
I tried using this in my SQL query but it's still returning value 1.56867.
CONVERT(decimal, myTable.Amout) = CONVERT(decimal, 2)
Can you advise?
Thanks.
You should really consider fixing your data model, and store numbers as numbers rather than strings.
That said, you need to specify a scale and a precision for the decimal, otherwise i defaults to decimal(38, 0) , which results in the decimal part being truncated. Something like:
convert(decimal(20, 5), myTable.Amout) = 2
This gives you 20 digits max, including 5 decimal digits. There is no need to explictly convert the right operand here (that's a literal number already).
If your column may contain values that are not convertible to numbers, you can use try_convert() instead of convert() to avoid errors.
The problem is that when converting the string '1.56867' to decimal, SQL server assumes you want 0 decimal places (as pointed out by #GMB), and rounds the value to the nearest integer (2).
select convert(decimal,'1.56867');
-------
2
Also, since your column is defined to hold character data, you should use the try_cast() function to avoid Error converting data type varchar to numeric. errors that would otherwise occur if non-numeric data is present in the column.
select *
from (values
('1.56867')
,('2.0')
,('2.0000')
,('2')
,(null)
,('non-numeric value')
) myTable(Amount)
where try_cast(Amount as decimal(38,19)) = 2
;
Amount
-----------------
2.0
2.0000
2
(3 rows affected)

How to convert string to numbers (if numeric), otherwise leave as string in SQL

my column has customer numbers that are both numeric and combinations of text and numbers. I only want to convert them if they are all numeric otherwise leave them as a string
ex.
91036
ab321
10001
Only convert 91036 and 10001 as numbers (using cast or convert) but leave ab321 as string. I tried isnumeric but this isn't a recognized function in the query builder I'm using. And if I convert using cast or convert the strings are disappearing.
This is an example based on Oracle, but I believe that the same principle would work elsewhere (at least, in databases that support regular expressions).
I don't quite understand what you meant by saying that you want to "convert" those values to numbers; convert where? I presume that they are currently stored in a VARCHAR2 (or some other "character" datatype column). There's no use in converting them to number an leave them in the same column, as that wouldn't do absolutely anything - they would still be treated as strings (stored in the character datatype column, remember?).
So, I've created another - NUMBER datatype column and will populate it with a number whenever possible.
Sample data:
SQL> create table test (col_char varchar2(10),
2 col_num number);
Table created.
SQL> insert into test (col_char)
2 (select '91036' from dual union
3 select 'ab321' from dual union
4 select '10001' from dual
5 );
3 rows created.
Update uses REGEXP_LIKE function which checks whether COL_CHAR looks like a number:
^ anchors you to the beginning of the string
\d+ takes as many consecutive digits as it can find
$ anchors you to the end of the string
which, all together, means that string must begin with a digit, must end with a digit, and everything in between have to be digits.
SQL> update test set
2 col_num = to_number(col_char)
3 where regexp_like(col_char, '^\d+$');
2 rows updated.
SQL> select * From test;
COL_CHAR COL_NUM
---------- ----------
10001 10001
91036 91036
ab321
SQL>
Things are getting somewhat more complex when there are decimals and/or thousands separators in a string, so you might need to alter both TO_NUMBER function and regular expression pattern. For example:
SQL> update test set
2 col_num = to_number(col_char, '999990D00000', 'nls_numeric_characters = '',.''')
3 where regexp_like(col_char, '^[0-9]+|(\,)[0-9]+$');
2 rows updated.
SQL> select * from test;
COL_CHAR COL_NUM
---------- ----------
10001 10001
91,036 91,036
ab321
SQL>

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

determine DB2 text string length

I am trying to find out how to write an SQL statement that will grab fields where the string is not 12 characters long. I only want to grab the string if they are 10 characters.
What function can do this in DB2?
I figured it would be something like this, but I can't find anything on it.
select * from table where not length(fieldName, 12)
From similar question DB2 - find and compare the lentgh of the value in a table field - add RTRIM since LENGTH will return length of column definition. This should be correct:
select * from table where length(RTRIM(fieldName))=10
UPDATE 27.5.2019: maybe on older db2 versions the LENGTH function returned the length of column definition. On db2 10.5 I have tried the function and it returns data length, not column definition length:
select fieldname
, length(fieldName) len_only
, length(RTRIM(fieldName)) len_rtrim
from (values (cast('1234567890 ' as varchar(30)) ))
as tab(fieldName)
FIELDNAME LEN_ONLY LEN_RTRIM
------------------------------ ----------- -----------
1234567890 12 10
One can test this by using this term:
where length(fieldName)!=length(rtrim(fieldName))
This will grab records with strings (in the fieldName column) that are 10 characters long:
select * from table where length(fieldName)=10
Mostly we write below statement
select * from table where length(ltrim(rtrim(field)))=10;