I have a table with a smallint column that contains percentages as whole numbers (i.e., 50, 75, 85, etc.)
When I divide this column by 100, as in
SELECT MY_COLUMN/100 AS PCT_AS_FRACTION
FROM MY_TABLE
the result is rounded to the nearest whole number.
For example, for a row that contains the number "50", I get zero as my result.
I can duplicate this with a simple statement:
SELECT 50 / 100 AS TEST_VALUE
Why is that, and how can I get more precision in my result?
When you do integer division (integer divided by integer) you always get an integer answer. 50/100 = .50, which is 0 in integer-speak.
Have you tried dividing MY_COLUMN by 100.0?
Cast whole numbers.
SELECT (cast(50 AS float)/100)
You're doing integer division.
50/100 is 0 with a remainder of 50.
You need to use floating point division.
NB - Be careful in that the remainder of integer division is not rounded. Rather, it is dropped. This is equivalent to calling the FLOOR sql function.
This is common, and is defined as such because when multiplying two integers, a fraction will never occur. Therefore a fraction-handling methodology is never assumed when multiplying integers, but the same cannot be said for integer division.
This can often have an impact when doing dateTime arithmetic in SQL.
When you are using /(Divide) operator it
Returns the data type of the argument with the higher precedence.
and
If an integer dividend is divided by an integer divisor, the result is
an integer that has any fractional part of the result truncated.
So, you need to cast at least one of the operands to appropriate type: decimal and numeric or float or real.
You're dividing 2 integers which results in another integer.
It should possible to cast that way, too
SELECT (50/100)::numeric;
Related
I know REAL data type is not accurate and normally for currency I should use numeric data type.
But, I'm asked to do some stuff and one of the conditions is that the data type is real.
When I try to do round((....),2) for example, I get that round function does not exist for this data type.
My question is, without converting, is there any function that can return a REAL value rounded to 0?
Many thanks!1
As you can see here it's no way to round without any type cast. It's only two kinds of function exists:
round(dp or numeric) - round to nearest integer
round(v numeric, s int) - round to s decimal places
Real = double precision. So you need to use convert anyway if you want to get some decimal places:
select round('123.456789'::real::numeric,2)
upd. Keep care about rounding+cast at big real numbers:
select round('12122156.567'::real::numeric, 2); --< rounding up to 6 digits, result = 12122200
select round('12122156.567'::real::DOUBLE PRECISION::numeric,2); --<< rounding result = 12122157
Or you can use round without decimal places:
select round('123.456789'::real)
round a numeric value to 0 after the dot?
ROUND(numeric_value, 0)
After investigation, converting to ::numeric is the only way around
I have a double type column in impala
while I am trying to cut it upto some decimal places
I got this error
ERROR: AnalysisException: No matching function with signature: truncate(DOUBLE, TINYINT).
e.g select truncate(cast(0.4893617021276596 as double),7);
any workaround will be welcome
You can use round():
select round(col, 6)
If you actually want a truncate, then subtract 0.0000005:
select round(col - 0.0000005, 6)
Using the DECIMAL type, it is possible to represent numbers with greater precision than the FLOAT or DOUBLE types can represent.
The maximum allowed precision and scale of the DECIMAL type are both 38.
Precision is the total number of digits, regardless of the location of the decimal point.
Scale is the number of digits after the decimal place.
To represent the number 8.54 without a loss of precision, you would need a
DECIMAL type with precision of at least 3, and scale of at least 2.
Example:
Note that the DECIMAL(17,16) type means there is a total of 17 digits, with 16 of them after the decimal point.
DECIMAL(17,16) 3.1415926535897932
You could ALTER your table with DECIMAL type as follow:
ALTER TABLE my_table CHANGE field field DECIMAL(precision, scale);
or as suggest #Gordon Linoff, you could use round() function.
I need to get a total of hours worked but my result always ends up in a rounded number. I need to show the real hours worked to two decimal places. Here is my code thus far:
CAST((datediff(mi,CONVERT(datetime,p.Punchin,114),CONVERT(datetime,p.Punchout,114)) - datediff(mi,CONVERT(datetime,p.Lunch_in,114),CONVERT(datetime,p.Lunch_out,114)))/60 AS decimal (12,2)) AS "Hours Worked"
Not sure where I am going wrong but assistance is greatly appreciated.
This is happening because of data type precedence. Since you're working with both integers on both sides of the expression, it's being implicitly converted to INT. Try diving by "60.00" or "CAST(60 AS DECIMAL(12,2))".
https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-ver15
Looks like you're getting the total number of minutes (an integer) and then dividing by 60 (an integer). Dividing an integer by an integer is integer division and will result in an integer with the fractional part dropped. THEN you're casting that integer to a decimal(12,2) but the fractional part is already gone.
Try changing /60 to /60.0 to avoid the integer division. I think that should fix it for you.
You can find more discussion of integer division in SQL server in these posts:
Integer division in sql server
How to get a float result by dividing two integer values using T-SQL?
select round((cast(56/3 AS DECIMAL (4,2))),1)
is showing 18 output instead of 19 , where as actual value is 18.66.
My Round function is not working
please help.
The problem is 56/3 is an integer calculation which means no floating point numbers.
You need to use floating point numbers in the initial calculation e.g. 56.0/3. Also, if you want to round to 19 then you need to round to the nearest whole number, ROUND(x, 1) will round to the first decimal place - you need to pass 0 to round up to 19.
SELECT ROUND((CAST(56.0/3 AS DECIMAL (4,2))),0)
Alternatively, you could switch ROUND for CEILING
select CEILING(CAST(56.0/3 AS DECIMAL(4,2)))
Your section of the code:
CAST( 56/3 AS DECIMAL )
First evaluates the 56/3 which returns 18. This is then cast to decimal, giving 18.0.
You need to cast either the numerator or denominator before the division occurs.
The round function is working fine -- it's just not using the input you think it is.
Convert one of your integer values before you divide the numbers:
select round(56/convert(DECIMAL (4,2),3),0);
If you do not so you divide integers which results in 18 not 18.66
I have a table with a smallint column that contains percentages as whole numbers (i.e., 50, 75, 85, etc.)
When I divide this column by 100, as in
SELECT MY_COLUMN/100 AS PCT_AS_FRACTION
FROM MY_TABLE
the result is rounded to the nearest whole number.
For example, for a row that contains the number "50", I get zero as my result.
I can duplicate this with a simple statement:
SELECT 50 / 100 AS TEST_VALUE
Why is that, and how can I get more precision in my result?
When you do integer division (integer divided by integer) you always get an integer answer. 50/100 = .50, which is 0 in integer-speak.
Have you tried dividing MY_COLUMN by 100.0?
Cast whole numbers.
SELECT (cast(50 AS float)/100)
You're doing integer division.
50/100 is 0 with a remainder of 50.
You need to use floating point division.
NB - Be careful in that the remainder of integer division is not rounded. Rather, it is dropped. This is equivalent to calling the FLOOR sql function.
This is common, and is defined as such because when multiplying two integers, a fraction will never occur. Therefore a fraction-handling methodology is never assumed when multiplying integers, but the same cannot be said for integer division.
This can often have an impact when doing dateTime arithmetic in SQL.
When you are using /(Divide) operator it
Returns the data type of the argument with the higher precedence.
and
If an integer dividend is divided by an integer divisor, the result is
an integer that has any fractional part of the result truncated.
So, you need to cast at least one of the operands to appropriate type: decimal and numeric or float or real.
You're dividing 2 integers which results in another integer.
It should possible to cast that way, too
SELECT (50/100)::numeric;