Weird decimal values obtained through SQL type casting - sql

I have a very peculiar situation happening while doing a simple division using GoogleSQL.
For example, variables involved:
Fruit_name -- String
price_purchased -- String
used_discount -- double
Example values:
fruit_name
price_purchased
used_discount
apple
5
0.8
pear
6
0.76
A simple division through SQL to find out original price:
SELECT DISTINCT
fruit_name,
CAST(price_purchased AS double),
used_discount,
CAST(price_purchased AS double) / (1 - used_discount) as original_price
FROM
fruit_table
I'm weirdly getting such a result:
fruit_name
price_purchased
used_discount
original_price
apple
5
0.8
25.000000000000007
pear
6
0.76
25
The original price for the apple should also give me a value of 25 exactly, just like how the pear's value was also at 25.
How is it that the value of the apple's original price could have that weird minuscule amount? Is this due to some type casting issue?
Thanks.

The division result is floating point value, you need to it to NUMERIC type:
SELECT
CAST(5 AS FLOAT64) / (1 - 0.8) AS float_original_price,
CAST(CAST(5 AS FLOAT64) / (1 - 0.8) AS NUMERIC) AS numeric_original_price
float_original_price
numeric_original_price
25.000000000000007
25
You can refer to the docs for Bigquery Numeric Types. Also, check this post : What is the difference between NUMERIC and FLOAT in BigQuery?

Related

Not getting the division correct in postgresql 15 [duplicate]

Postgres is giving the wrong result for division when the denominator is greater than the numerator.
select 2/4 gives 0, select 4/2 works correct.
But select 2/4 should actually return 0.5
but it is returning 0 as integer
Postgres does integer division on integers. Ironically, it does not do integer averages on avg(), but that is a different matter.
One solution is simply converting one of the value to numeric:
select 2/4, 2::numeric/4
Postgres will add decimal places for numerics.
Try a floating point division, as in:
select 2.0 / 4 -- shows 0.5
Or:
select 1.0 * 2 / 4 -- shows 0.5

finding percentages between 2 different columns in sql

I was create this query:
select first_price, last_price, cast((sum(1 - (first_price / nullif(last_price,0)))) as double) as first_vs_last_percentages
from prices
group by first_price, last_price
having first_vs_last_percentages >= 0.1
unfortunately this is my wrong data in first_vs_last_percentages col
ID
first_price
last_price
first_vs_last_percentages
1
10
11
1-(10/11) = 1.0
2
66
68
1-(66/68) = 1.0
It was supposed to return this output:
ID
first_price
last_price
first_vs_last_percentages
1
10
11
1-(10/11) = 0.0909
2
66
68
1-(66/68) = 0.0294
if someone has a good solution and it will be in presto syntax it will be wonderful.
It seems you got struck by another case of integer division (your cast to double is a bit late), update the query so the divisor or dividend type changes (for example by multiplying one of them by 1.0 which is a bit shorter then cast to double):
select -- ...
, sum(1 - (first_price * 1.0) / nullif(last_price, 0)) first_vs_last_percentages
from ...
P.S.
Your query is a bit strange, not sure why do you need grouping and sum here.
It depends on which database engine you work upon. Typically, most query confusion rely on either conceptual or syntatic mistakes. In either one or the other cases, it seek to operate a row-percentage double 100.0*(last-first)/first. It means, you can drop the group by and having, since we MUST NOT group by double values, rather intervals they belong.
select
first_price,
last_price,
CASE
WHEN first_price = 0 THEN NULL
ELSE (last_price-first_price)/first_price
end as first_vs_last_percentage
from prices

How to divide integers in Oracle SQL to produce floating point numbers?

I have just started learning Oracle SQL. I am trying to divide two columns of numeric datatype which is same as an integer, I think. I want to create a new column in the table or float data type, divide an existing numeric column by an integer and put its value into the float column. I am using this code for the division and updating part:
update Student set AVERAGE = TOTAL/3;
Here, TOTAL is the numeric column and AVERAGE is float. But when I print the table using:
select * from Student;
, AVERAGE is shown with rounded values of the division. I tried two solutions that I found on the internet:
update Student set AVERAGE = (TOTAL*1.00)/3;
And:
update Student set AVERAGE = cast(TOTAL as float(2))/3;
But both are not working. What am I doing wrong?
Here is the output I am getting:
ROLL_NO SNAME MATHS CHEM PHY TOTAL AVERAGE
---------- --------------- ---------- ---------- ---------- ---------- ----------
101 abcd 56 68 80 204 70
102 efgh 81 78 70 229 80
103 ijkl 69 73 78 220 70
104 mnop 90 89 92 271 90
105 qrst 80 89 79 248 80
First, you need to understand what FLOAT datatype in Oracle means.
The Oracle FLOAT data type is the subtype of the NUMBER data type.
Synatx:
FLOAT(p)
p is precision in Binary bits.
Following formula is used to convert between binary and decimal
precision: Decimal = 0.30103 * Binary
Now, According to the result you are getting, I think your column (AVERAGE) datatype is FLOAT(1).
If you need more precision then you need to alter your table with more precision value in Binary.
Let's take an example:
CREATE TABLE TEST (
f1 FLOAT,
f2 FLOAT(1),
f3 FLOAT(4),
f4 FLOAT(7)
);
INSERT
INTO
TEST(
f1,
f2,
f3,
f4
)
VALUES(
10 / 3,
10 / 3,
10 / 3,
10 / 3
);
select * from TEST;
Output:
db<>fiddle demo
If you do not provide any precision then Oracle will take the maximum precision(126 bits
--> 37 decimal).
In the above example, the data type of the column f1, f2, f3, and f4 is FLOAT, FLOAT(1), FLOAT(4), and FLOAT(7).
The corresponding precision in decimal digits of the column f1, f2 <-- (Your case), f3 and f4 is 37(126 * 0.30103), 1 (1 * 0.30103) <-- (Your case), 2 (4 * 0.30103), and 3 (7 * 0.30103).
So, Conclusion is --> alter your table and change the precision of the AVERAGE column's FLOAT datatype according to your requirement.
Cheers!!
This is a little long for a comment.
The column average is going to be displayed based on the datatype of that column. Oracle will convert the "numbers" being divided so the result is accurate, I think using the number type.
You can run the following code to see that the division result is always the same:
select cast(10 as int) / cast(3 as int),
cast(10 as numeric) / cast(3 as numeric),
cast(10 as float) / cast(3 as float)
from dual;
So the data type of the operands doesn't make a difference.
On the other hand, the data type of the result does. These produce different results:
select cast(10 / 3 as int),
cast(10 / 3 as float),
cast(10 / 3 as number),
cast(10 / 3 as numeric(5, 1))
from dual;
In Oracle the NUMBER data type is already a floating point type. It's unusual in that it's a base-10 floating point number type so it's safe to use for calculations involving money, but it's still a floating point type. Docs here
It is possible to define a NUMBER which holds only integers by defining a subtype or a particular field as having 0 for the scale component, e.g.
nInt_value NUMBER(10,0);
or
SUBTYPE TEN_DIGIT_INTEGER_TYPE IS NUMBER(10,0);
in which case nInt_value will only be able to hold whole numbers of 10 digits or less.
Note that SUBTYPE is only available in PL/SQL - in other words, you can't define a SUBTYPE in a PL/SQL module and then use it as a database field. Docs here

PostgreSQL 10.1 incorrect division output

Postgres is giving the wrong result for division when the denominator is greater than the numerator.
select 2/4 gives 0, select 4/2 works correct.
But select 2/4 should actually return 0.5
but it is returning 0 as integer
Postgres does integer division on integers. Ironically, it does not do integer averages on avg(), but that is a different matter.
One solution is simply converting one of the value to numeric:
select 2/4, 2::numeric/4
Postgres will add decimal places for numerics.
Try a floating point division, as in:
select 2.0 / 4 -- shows 0.5
Or:
select 1.0 * 2 / 4 -- shows 0.5

Redshift division result does not include decimals

I'm trying to do something really quite basic to calculate a kind of percentage between two columns in Redshift. However, when I run the query with an example the result is simply zero because the decimals are not being covered.
code:
select 1701 / 84936;
Output:
I tried :
select cast(1701 / 84936 as numeric (10,10));
but the result was 0.0000000000.
How could I solve this silly thing?
It is integer division. Make sure that at least one argument is: NUMERIC(accurate data type)/FLOAT(caution: it's approximate data type):
/ division (integer division truncates the result)
select 1701.0 / 84936;
-- or
SELECT 1.0 * 1701 / 84936;
-- or
SELECT CAST(1701 AS NUMERIC(10,4))/84936;
DBFiddle Demo
When mixing data types the order counts
Note that the order of the elements in a math expression counts for the data type of the result.
Let's assume that we intend to calculate the percentage unit_sales/total_sales where both columns (or numbers) are integers.
See and try with this code here.
-- Some dummy table
drop table if exists sales;
create table sales as
select 3 as unit_sales, 9 as total_sales;
-- The calculations
select
unit_sales/total_sales*100, --> 0 (integer)
unit_sales/total_sales*100.0, --> 0.0 (float)
100.0*unit_sales/total_sales --> 33.3 (float and expected result)
from sales;
The output
0 | 0.0 | 33.33
The first column is 0 (integer) because of 3/9=0 in an integer division.
The second column is 0.0 because SQL first got the integer 0 (3/9), and later, SQL converts it to float in order to perform the multiplication by 100.0.
The expected result.
The non-integer 100.0 at the beginning of the expression force a non-integer calculation.