Call now: 252-767-6166  
Oracle Training Oracle Support Development Oracle Apps

 
 Home
 E-mail Us
 Oracle Articles
New Oracle Articles


 Oracle Training
 Oracle Tips

 Oracle Forum
 Class Catalog


 Remote DBA
 Oracle Tuning
 Emergency 911
 RAC Support
 Apps Support
 Analysis
 Design
 Implementation
 Oracle Support


 SQL Tuning
 Security

 Oracle UNIX
 Oracle Linux
 Monitoring
 Remote s
upport
 Remote plans
 Remote
services
 Application Server

 Applications
 Oracle Forms
 Oracle Portal
 App Upgrades
 SQL Server
 Oracle Concepts
 Software Support

 Remote S
upport  
 Development  

 Implementation


 Consulting Staff
 Consulting Prices
 Help Wanted!

 


 Oracle Posters
 Oracle Books

 Oracle Scripts
 Ion
 Excel-DB  

Don Burleson Blog 


 

 

 


 

 

 

 
 

Advanced Oracle SQL: Rounding and Truncating Functions

Oracle Tips by Laurent Schneider

 

Laurent Schneider is considered one of the top Oracle SQL experts, and he is the author of the book "Advanced SQL Programming" by Rampant TechPress.  The following is an excerpt from the book.

SELECT
   X.COLUMN_VALUE X,
   ROUND(X.COLUMN_VALUE) "ROUND(X)",
   TRUNC(X.COLUMN_VALUE) "TRUNC(X)",
   FLOOR(X.COLUMN_VALUE) "FLOOR(X)",
   CEIL(X.COLUMN_VALUE) "CEIL(X)"
FROM
   TABLE(SYS.ODCINUMBERLIST(-9.9,-1.1,-0.5,0.5,1.1,9.9)) X;
         X   ROUND(X)   TRUNC(X)   FLOOR(X)    CEIL(X)
---------- ---------- ---------- ---------- ----------
      -9.9        -10         -9        -10         -9
      -1.1         -1         -1         -2         -1
       -.5         -1          0         -1          0
        .5          1          0          0          1
       1.1          1          1          1          2
       9.9         10          9          9         10

TRUNC removes the decimal part for both negatives and positives. Therefore, TRUNC(-x) is equal to -TRUNC(x). ROUND returns the closest value and when both upper and lower values are equidistant, it rounds up to the higher positive value or the lower negative value, i.e. ROUND(-x)=-ROUND(x).

FLOOR(x) returns the highest integer that is not greater than x (the lower bound) and CEIL(x) returns the lowest integer that is not less than x (the upper bound).

ROUND and TRUNC accept a second argument to round or truncate at another decimal place than the default unit:

SELECT
   X.COLUMN_VALUE X,
   ROUND(X.COLUMN_VALUE, -2) "ROUND(X,-2)",
   TRUNC(X.COLUMN_VALUE, -2) "TRUNC(X,-2)",
   ROUND(X.COLUMN_VALUE, 0) "ROUND(X)",
   TRUNC(X.COLUMN_VALUE, 0) "TRUNC(X)",
   ROUND(X.COLUMN_VALUE, 2) "ROUND(X,2)",
   TRUNC(X.COLUMN_VALUE, 2) "TRUNC(X,2)",
FROM
   TABLE(SYS.ODCINUMBERLIST(1234.4321,-9876.6789)) X;
         X ROUND(X,-2) TRUNC(X,-2)   ROUND(X)   TRUNC(X) ROUND(X,2) TRUNC(X,2)
---------- ----------- ----------- ---------- ---------- ---------- ----------
 1234.4321        1200        1200       1234       1234     1234.43    1234.43
-9876.6789       -9900       -9800      -9877      -9876    -9876.68   -9876.67

The second argument is an integer that defines at which decimal place the rounding takes place, so ROUND(x, 2) will round to the hundredth.

ROUND and TRUNC also work for dates:

SELECT
   SYSDATE,
   ROUND(SYSDATE),
   TRUNC(SYSDATE)
FROM
   DUAL;
SYSDATE             ROUND(SYSDATE)      TRUNC(SYSDATE)
------------------- ------------------- -------------------
25.01.2008 21:08:26 26.01.2008 00:00:00 25.01.2008 00:00:00

Unfortunately, TIMESTAMP is cast to DATE when using TRUNC and ROUND.

TRUNC and ROUND accept a second argument to truncate or round to a specific period of time:

SELECT
   D.COLUMN_VALUE "D",
   FMT.COLUMN_VALUE "FMT",
   ROUND(D.COLUMN_VALUE, FMT.COLUMN_VALUE) "ROUND(D,FMT)",
   TRUNC(D.COLUMN_VALUE, FMT.COLUMN_VALUE) "TRUNC(D,FMT)"
FROM
   TABLE(SYS.ODCIDATELIST(TIMESTAMP '1994-08-18 12:30:30.00')) D,
   TABLE
   (
      SYS.ODCIVARCHAR2LIST
      (
         'MI', 'HH', 'DD', 'D', 'W', 'WW', 'IW', 'MM', 'Q', 'Y', 'IY', 'CC'
      )
   ) FMT;

D                   FMT ROUND(D,FMT)        TRUNC(D,FMT)
------------------- --- ------------------- -------------------
18.08.1994 12:30:30 MI  18.08.1994 12:31:00 18.08.1994 12:30:00
18.08.1994 12:30:30 HH  18.08.1994 13:00:00 18.08.1994 12:00:00
18.08.1994 12:30:30 DD  19.08.1994 00:00:00 18.08.1994 00:00:00
18.08.1994 12:30:30 D   21.08.1994 00:00:00 14.08.1994 00:00:00
18.08.1994 12:30:30 W   22.08.1994 00:00:00 15.08.1994 00:00:00
18.08.1994 12:30:30 WW  20.08.1994 00:00:00 13.08.1994 00:00:00
18.08.1994 12:30:30 IW  22.08.1994 00:00:00 15.08.1994 00:00:00
18.08.1994 12:30:30 MM  01.09.1994 00:00:00 01.08.1994 00:00:00
18.08.1994 12:30:30 Q   01.10.1994 00:00:00 01.07.1994 00:00:00
18.08.1994 12:30:30 Y   01.01.1995 00:00:00 01.01.1994 00:00:00
18.08.1994 12:30:30 IY  02.01.1995 00:00:00 03.01.1994 00:00:00
18.08.1994 12:30:30 CC  01.01.2001 00:00:00 01.01.1901 00:00:00

MI truncates to the minute, HH to the hour, DD to the day, MM to the month, Q to the quarter, Y to the year and CC to the century. When rounding, MM rounds up from the 16th day and Q from the 16th day of the second month. IW is fairly useful as it truncates to Monday regardless of session parameters.

D is the first day of the week, which is Sunday when the territory is America. W is the week of the month and WW is the week of year.

SELECT
   DATE '2008-01-01',
   DATE '2008-02-01'
FROM
   DUAL;
DATE'2008-01-01'       DATE'2008-02-01'      
---------------------- ----------------------
Tuesday   01 January   Friday    01 February

2008 starts on a Tuesday, February starts on a Friday and the territory is set to America:

SELECT
   TRUNC(DATE '2008-02-14','IW') IW,
   TRUNC(DATE '2008-02-14','W') W,
   TRUNC(DATE '2008-02-14','WW') WW,
   TRUNC(DATE '2008-02-14','D') D
FROM
   DUAL;
IW         W          WW         D
---------- ---------- ---------- ----------
Mon 11 Feb Fri 8 Feb  Tue 12 Feb Sun 10 Feb

IW truncates to Monday (always), W to Friday (1st day of month), WW to Tuesday (1st day of year) and D to Sunday (in America).

Rather than using TO_NUMBER(TO_CHAR(d, 'D')) to get the day of the week, it is possible to use TRUNC:

SELECT
   TRUNC(SYSDATE)-TRUNC(SYSDATE,'IW') "DAY"
FROM
   DUAL;
TRUNC(SYSDATE)-TRUNC(SYSDATE,'IW')
----------------------------------
                                 4

Monday is 0 and Sunday is 6. The main advantage of this method is that it can be used in materialized views, function-based indexes and session-independent views and procedures.

SELECT
   COLUMN_VALUE N,
   ROUND(COLUMN_VALUE*20)/20 "ROUND(N)"
FROM
   TABLE(SYS.ODCINUMBERLIST(1.12, 2.53, 5.25));
         N      ROUND(N)
---------- -------------
      1.12          1.10
      2.53          2.55
      5.25          5.25

The value is multiplied by 20 before rounding. The rounding is then done at a five-hundredths granularity.

SELECT
   COLUMN_VALUE D,
   DATE '2000-01-01'+
      TRUNC((COLUMN_VALUE - DATE '2000-01-01')*96)/96 "TRUNC(D)"
FROM
   TABLE(SYS.ODCIDATELIST(
      TIMESTAMP '2009-02-21 05:25:45',
      TIMESTAMP '2009-02-25 06:31:30'
  ));

D                   TRUNC(D)
------------------- -------------------
2009-02-21 05:25:45 2015-02-21 05:15:00
2009-02-25 06:31:30 2015-02-25 06:30:00

The difference with an arbitrary date is multiplied by 96 to split the day in 96 periods of 15 minutes (24 hours times 4 quarters = 96 periods).

Some periods could be switched to default calendar periods by adding a period before the TRUNC:

SELECT
   COLUMN_VALUE D,
   TO_CHAR(TRUNC(ADD_MONTHS(COLUMN_VALUE, 3), 'Y'), '"FY"YY') "FY"
FROM
   TABLE
   (
      SYS.ODCIDATELIST(
         DATE '2008-09-30',
         DATE '2008-12-21',
         DATE '2009-02-25'
      )
   );

D          FY
---------- ----
2008-09-30 FY08
2008-12-21 FY09
2009-02-25 FY09

The fiscal year starts in October, three months before the calendar year. This three-month period is added before truncating the date.

 


 

 

��  
 
 
Oracle Training at Sea
 
 
 
 
oracle dba poster
 

 
Follow us on Twitter 
 
Oracle performance tuning software 
 
Oracle Linux poster
 
 
 

 

Burleson is the American Team

Note: This Oracle documentation was created as a support and Oracle training reference for use by our DBA performance tuning consulting professionals.  Feel free to ask questions on our Oracle forum.

Verify experience! Anyone considering using the services of an Oracle support expert should independently investigate their credentials and experience, and not rely on advertisements and self-proclaimed expertise. All legitimate Oracle experts publish their Oracle qualifications.

Errata?  Oracle technology is changing and we strive to update our BC Oracle support information.  If you find an error or have a suggestion for improving our content, we would appreciate your feedback.  Just  e-mail:  

and include the URL for the page.


                    









Burleson Consulting

The Oracle of Database Support

Oracle Performance Tuning

Remote DBA Services


 

Copyright © 1996 -  2020

All rights reserved by Burleson

Oracle ® is the registered trademark of Oracle Corporation.