Is trunc and round the same with negative arguments?
SQL> select round(123456.76,-4) from dual;
ROUND(123456.76,-4)
-------------------
120000
SQL> select trunc(123456.76,-4) from dual;
TRUNC(123456.76,-4)
-------------------
120000
No, behavior depends on the value of the significant digit (the 3rd digit (the 3) is the significant one in your case, as it is below 5 round and trunc do the same )
try select trunc(125456.76,-4) from dual (result is 120000) vs select round(125456.76,-4) from dual (result is 130000). Now when the significant digit is 5 (or higher) the results of trunc and round differ.
ROUND is related to round figure of given value.
TRUNC is related to truncation of given values.
In round case of given example, four places till 4th place prior to decimal point padded with 0.
But in trunc case, four places till 4th place prior to decimal point replacd with 0.
TRUNC - depending on second parameter it returns specified decimal places that is specified in second argument. Ex:
trunc(25.656) -- 25
trunc(25.656, 1) -- 25.6
trunc(25.656, 2) -- 25.65
ROUND - round off the given number to the nearest value. Ex:
round(66) -- 70
round(64) -- 60
round(65.7) -- 66
round(65.3) -- 65
Related
One of the columns of my table has values that can typically range from 3500 to 8 million. Is it possible to specify a format that can divide the number when formatting?
For example, I have the following values:
3500
81000
1678500
Ideally I would like a format value (coming from another config table) that would format the numbers in "thousands" with 1 decimal place:
3.5
81.0
1678.5
But this format value could also be different for other cases, so they could be formatted in millions with two decimal places:
0.00
0.08
1.68
Is this possible, or do I need to divide the numbers myself before applying the formatting?
Is this possible, or do I need to divide the numbers myself before applying the formatting?
You need to do the division. You can use CASE WHEN, by the way, if you aren't having numeric values to track what to divide by:
SELECT tablevalue / CASE divby WHEN 'thousand' THEN 1000 WHEN 'million' THEN 1000000 ELSE 1 END
I presume you'll have some column in your "format" table that also specifies what to divide by..
So you don't want to add a column.. you can store the info in the existing column.. you just have to work more to get it out:
SELECT
TO_CHAR(
somenumber / CASE RIGHT(format, 1) WHEN 'k' THEN 1000 WHEN 'M' THEN 1000000 END,
LEFT(format, -1)
)
So now you can make your format like 99D99k and the k will cause a divide by 1000 and the result is formatted to 99.99, so if you have 1234, format 9.99k you'll get '1.23'out of it.
If you want the [k] at the start it's just some jiggling of the LEFT and RIGHT functions..
TO_CHAR(
somenumber / CASE LEFT(format, 3) WHEN '[k]' THEN 1000 WHEN '[M]' THEN 1000000 END,
RIGHT(format, -3)
)
I have an age column which calculates age for each member in my report.The output is a whole number followed by a decimal point and numbers. I would like the first number only right after the decimal point .
I tried trunc but it gives me everything before the decimal and then the number I want after .Then I tried to trunc with a call out with a comma and it doesnt work.
trunc(age,',')
Example -
age 15.7
expected output 7
Here the mathematical answer
take the decimal part by susbriacting the whole part (trunc).
multiply by 10 and take the whole part
.
with age as (select 15.7231 age from dual)
select trunc(10*(age-trunc(age))) dp1 from age
DP1
----------
7
try like below
select substr(to_char(15.7,'9999.0'),-1,1) as col from dual
it will return 7
Multiply by 10, trunc it and take the remainder of the division by 10.
with age as (select 15.7231 age from dual)
select mod(trunc(10*age), 10) dp from age
Output:
DP
--
7
Regarding DateDiff function
select datediff(current_date, '-2018-01-21');
what is - here as I know datediff(enddata,startdate)
if we mention minus for startdate it getting number values 1474138
can please help to understand
Below query confirms that a negative date is similar to a negative integer. If you subtract a negative number to a positive number, it is the same as adding their absolute values (ignoring the signs). For example; 8 - (-4) = 8 + 4
Thus, since the minimum date value for date type is '0000-01-01', we measure the number of days from year -2018 to 0000 and add to the number of days from 0000 to 2018. Then, we get 1474137 ( = 737122 + 737015). Hope this helps. Thanks.
Query:
select datediff('2018-03-02', '0000-01-01'), datediff('0000-01-01', '-2018-03-01'), datediff('2018-03-02', '-2018-03-01')
Result:
737122 737015 1474137
Again, 737122 + 737015 = 1474137. There are 1474137 days since 2018-Mar-01 BC.
How does dual work? I have executed this with many values Select Round(45.926,-1) from dual it prints 50 while
Select Round(45.926,-2) from dual prints 0.
When using ROUND function, the second parameter represents the places after decimal to be taken in result. So, following are results:
SELECT ROUND(45.926) FROM dual;
Result: 46 because no places after decimal to be considered.
SELECT ROUND(45.926, 1) FROM dual;
Result 45.9, consider 1 place after decimal
SELECT ROUND(45.926, -1) FROM dual;
Result: 50, considering the value to be 4.5926, rounding it to 5 and then printing the result.
SELECT ROUND(45.926, -2) FROM dual;
Result: 0, considering the value to be 0.45926, rounding it to 0 and then printing the result in original 10x which is 0x100 = 0.
If you'd taken,
SELECT ROUND(55.926, -2) FROM dual;
Then result will be 100 because it would be like, rounding 0.55926 to 1 and then 10x which 1x100 = 100.
Round(n,m) - rounds the number n to m decimal places.
For m = -1, it rounds the number to tenth place making 45.926 to 50 as it is greater than 45
For m = -2, it rounds the number to 100 place. Since 45.926 is less than 50, it becomes 0. If you try round(51,-2) you should get 100
I'm trying to understand the repercussions of having a column with real data type in a database(Sql Server) table, in my scenario. I have a column in my database with real datatype. The data is static, its always one of the values in range 0.0, 0.1, 0.2.. to 1.0.
Use Case:
I have to Sum up the values in the column and use the sum value in some arithmetic calculations which include financial data.
Concern?:
When I sum up values in the column it gives me result with more decimal places.
Test:
I want sum up the column values and use it in multiplication and division calculations.
I want to repeat #1 for same set of values in a column with decimal and float data types.
Procedure: I have created three different tables with a single column and same set of values but different data types, one with decimal, float and real. And perform the arithmetic calculations on each of them.
CREATE TABLE #tReal(d real);
INSERT INTO #tReal
SELECT 0.1 UNION ALL
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 0.9 UNION ALL
SELECT 1 UNION ALL
SELECT 0.9 UNION ALL
SELECT 1;
select SUM(d) from #tReal
Expected Result : 5.9
Actual Result : 5.8999999538064
And, If I perform round operation on the sum the result is as expected
declare #sumofd real
select #sumofd = SUM(d) from #tReal
select round(#sumofd , 1)
Result: 5.9
Also, if I update datatype from real to float
CREATE TABLE #tfloat(d float);
INSERT INTO #tfloat
SELECT 0.1 UNION ALL
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 0.9 UNION ALL
SELECT 1 UNION ALL
SELECT 0.9 UNION ALL
SELECT 1;
select SUM(d) from #tfloat
Expected Result : 5.9
Actual Result : 5.9
And, This is the same case if I update datatype from real to decimal
CREATE TABLE #tDecimal(d DECIMAL(3,2));
INSERT INTO #tDecimal
SELECT 0.1 UNION ALL
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 0.9 UNION ALL
SELECT 1 UNION ALL
SELECT 0.9 UNION ALL
SELECT 1;
select SUM(d) from #tDecimal
Expected Result : 5.94
Actual Result : 5.94
And, If I perform some basic arithmetic operations on the sum, without rounding, like
declare #sumofdReal real
declare #sumofdFloat float
declare #sumofdDecimal decimal(3,2)
select #sumofdReal = SUM(d) from #tReal
select #sumofdFloat = SUM(d) from #tfloat
select #sumofdDecimal = SUM(d) from #tDecimal
Multiplication:
select #sumofdReal * 2
Result: 11.8
select #sumofdFloat * 2
Result: 11.8
select #sumofdDecimal * 2
Result: 11.88
Division:
select #sumofdReal / 2
Result: 2.95
select #sumofdFloat / 2
Result: 2.95
select #sumofdDecimal / 2
Result: 2.97000
Drop Tables:
drop table #tReal
drop table #tfloat
drop table #tDecimal
Following are my questions
In my scenario, having a datatype as real will have any repercussions?
If #1 is yes, what kind of repercussions? Do I have to change datatype to float or decimal? Why?
If #1 is No, Why? Please explain?
Is there a point to which float and real types can produce exact result and anything beyond it rounding errors will show up?
real in SQL Server is a synonym for float(24), which takes 4 bytes and up to 7 digits of precision.
float by itself is the same as float(53) which is also the same as double which takes up 8 bytes and has up to 15 digits of precision.
In my scenario, having a datatype as real will have any repercussions?
Possibly. decimal, float, and real have different characteristics and are not fully interchangeable. If you want to maintain the exact decimal representation, use the decimal datatype with the appropriate scale and precision. If your numbers represent imprecise data (such as temperature, height, time, or other "natural" measurements that cannot be measured without some imprecision) and want faster mathematical operations then use float (or real if you don;t need more than 7 digits of precision.
When I sum up values in the column it gives me result with more decimal places.
When you add floating point numbers, SQL determines how big the result can be and will use the appropriate data type. When you add two reals, the result could have more than 7 digits of precision, so it may use float as the resulting data type.
Do I have to change datatype to float or decimal? Why?
Use float if you may have more than 7 digits of precision, don't need absolute precision from a decimal standpoint, and want to use a floating-point type for faster calculations.
If you want a fixed scale and precision and want to minimize the imprecision involved with floating point numbers use decimal.
Working with floating-point values always has repercussions, because they are not represented exactly and some rounding errors will always occur. You have to be most careful when comparing values with constants, e.g. if (a == 0.0) as this won't always work if 'a' is the result of mathematical operations. Float and Decimal just give you different ranges and precisions.
If you are using these values in financial calculations, then you should always (pretty much) use decimal types, otherwise you will run into issues with floating point rounding at some point. People get very wound up when you start losing pennies.
You may want to read some more on floating point arithmetic here:
http://floating-point-gui.de/
Decimal types will not be subject to these and should be exact.
For an example, you will eventually run into the situation where you try and round a number to 2 DP, e.g. 0.695, which you would expect to round up to 0.70.
DECLARE #x REAL = 0.695
SELECT ROUND(#x, 2)
-- outputs 0.69
DECLARE #y DECIMAL(6,4) = 0.695
SELECT ROUND(#y, 2)
-- outputs 0.7000
This is down to the fact that you cannot accurately represent 0.695 as a floating point number and it is in fact marginally less than 0.695 as saved.