Divide integers and round to 3 decimal places with one cast? - sql

Is there a way to divide two integers and round to 3 decimal places with only one cast/convert?
All the examples I see convert to decimal, then round. Some cast both numerator and denominator, etc. I've seen round with floor or ceiling, etc.
I just want to use one cast and I'm done.
For example, 1/3 would be 0.333. 5/3 is 1.667
I'm doing this to cast that result as varchar.

Dividing two int values t-sql has only two possible outcomes:
error 8134 (division by zero)
an int value again
It should be sufficient to coerce one of the operands to numeric:
select round(1.0/3,3,0)
To avoid trailing zeroes, another way:
select cast(1.0/3 as decimal(18,3))
This of course works only with numeric literals. If you have a column or parameter value, a cast is still needed.
This feeble attempt at code golf shaves off one more character:
select convert(decimal(9,3),1.0/3)

Related

PostgreSQL- Round REAL data type (yes, I know numeric exist)

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

SQL Round cast to float

I have a problem with round in SQL Server 2014: when I round a number to 2 decimal places sometimes the rounded number is different if I cast to float before or not.
For example, if I execute:
select round(cast(3.945 as float),2)
select round(3.945,2)
I have:
3.94
3.950
But if I execute:
select round(cast(3.935 as float),2)
select round(3.935,2)
I have:
3.94
3.940
It seems incorrect, rounding 3.935 and 3.945 casting to float before, I obtain the same value. Is this a bug?
The problem here is that float is a binary floating point type, where the representation is an approximation of the value. Floats do not losslessly convert to or from base 10, because there is no power of 10 that is also a power of 2. So when this is converted it is done in a way that leaves a roundoff error that pushes the value just before the rounding threshold.
Oddly I cannot reproduce the same behaviour on PostgreSQL and I am not entirely sure why (it may be that on PostgreSQL, round takes a numeric value and this forces a conversion back).
Never use floats where absolute accuracy is required. This occurs not only in databases, but in almost every programming language as well.
As #ChrisTravers says in his answer the issue with rounding a float is that you're not getting exact arithmetic. i.e. That explains why round(3.945,2) rounds up to 3.95 whilst round(3.945E0,2) effectively rounds down to 3.94.
If you're wondering why you see more than 2 decimal places in some cases, that's because of the type you're dealing with. i.e. 3.94 is a float, so doesn't have a specified number of decimal places; whilst 3.950 is the result of rounding a decimal(4,3); which even though we've rounded to 2 decimal places doesn't affect the precision of the type (i.e. it's still decimal(4,3); not converted to decimal(4,2) or decimal(3,2)).
If the purpose of this rounding is for display purposes, you're best of using the str function. i.e.
select str(3.945,4,2) --decimal
select str(3.945E0,4,2) --float
In the above the 4 is the length of the string (i.e. includes the decimal point as a character), and the 2 is the number of decimal places to show.
NB: In this scenario you're chaning the data type to varchar(4).
The below code allows you to see what type you get after performing an operation:
declare #result sql_variant = str(3.945E0,4,2)
select sql_variant_property(#result, 'BaseType') [BaseType]
,sql_variant_property(#result, 'MaxLength') [MaxLength]
,sql_variant_property(#result, 'Precision') [Precision]
,sql_variant_property(#result, 'Scale') [Scale]

Round a value to two decimal places in SQL

I am trying to round a value in SQL, here is the code that I have:
select round(600.000,2)
How do I get the value 600.00?
Instead of round() convert to a decimal:
select cast(600.000 + 0.5 as decimal(10, 2) )
round() changes the value but it might not change the type of the result. Hence, you might still see extra decimal points (depending on the database and the application). Converting to a decimal with two digits of precision converts both the value and the type.

SQL keep two decimal places for integers after converting cent into dollar

I am trying convert number values stored in the database as cents into dollar and keep 2 decimal places.
The following code will work only if v_cent/100.00 is NOT integer
SELECT CAST(ROUND(v_cent/100.00, 2) AS NUMERIC(8,2)) FROM DUAL;
If v_cent = 20000 then the result is 200.
How could I reserve 2 decimal places even if the result is integer?
Use to_char(), say to convert this to an output format with two decimal places:
select to_char(v_cent / 100.0, 'FM999999.99')
from dual;
As for your formulation it is doing the right thing. The only issue is that the decimal points are not printed out by default.

SQL set floating point precision

For a SQL int that is being converted to a float, how do I set the precision of the floating point number?
This is the selection I would like to truncate to two or 3 decimal places:
AVG(Cast(e.employee_level as Float))avg_level,
Thanks!
In TSQL, you can specify two different sizes for float, 24 or 53. This will set the precision to 7 or 15 digits respectively.
If all you want to do is truncate to a set number of decimal places, you can use ROUND, ie:
ROUND(AVG(CAST(e.employee_level as float)), 3)
As a general rule, you can't specify the number of digits after the decimal point for a floating-point number. Floating point data types store the closest floating-point approximation to any given value. The closest floating-point approximation is unlikely to have the number of digits you want. Although you might be able to suppress every digit after the third one, that will only change the appearance of the value, not the value itself.
Integers are a different story. An integer--stored, converted, or cast to a floating-point data type--will be stored exactly over a large range. Floating-point data types don't have to store any fractional units for integers.
I'd suggest, though that the best practice for you is to
avoid casting integers to floating-point if you don't need fractional units, or
cast integers to decimal or numeric if you do need fractional units, or
handle display issues entirely in application code.
I have had the same issue when calculating a percentage and needing a resulting string value.
Example: 68 is what % of 379
Result is a float = 17.9419525065900
You can cast/convert to Numeric with the Precision = 2 and get 17.94
If you need the value as a string you can then cast it as a VarChar if needed.
You can use Round() as well but in this case it only makes 17.9419525065900 = 17.9400000000000.
You can also use Ceiling() and Floor() to get the next highest or lowest integer.
Ceiling(17.9419525065900) = 18
Floor(17.9419525065900) = 17
Using these combinations you should be able to achieve a result in any format you need.