You are on page 1of 6

Report Subtotals and Totals Using Select ROLLUP in Oracle

By Jay Wortman, Independant Consultant

Corporate Headquarters Embarcadero Technologies 100 California Street 12th Floor San Francisco, CA 94111 www.embarcadero.com

EMEA Headquarters Embarcadero Technologies, Ltd. Thames House 17 Marlow Road Maidenhead Berkshire SL6 7AA United Kingdom www.embarcadero.co.uk

Report Subtotals and Totals Using Select ROLLUP in Oracle

Data Warehousing has been a major thrust of data base vendors for the past several years. Oracle continues to enhance its product for Data Warehousing(as well as OLTP and Web applications.) Some major Oracle 8i Release 8.1 Data Warehouse enhancements, amongst others, are: Table Partitioning enhancements. In addition to Range Partitioning, it now supports Hash partitioning and Composite(Hash Partitioning within Range Partitioning). Enhancements to Parallel Execution. Additions to parallel data loading and queries execution in parallel. Transportable Tablespaces. Unhooking a tablespace from one database and installing it into another.

CREATE TABLE Company_Sales( Year NUMBER(4), Country VARCHAR2(10), Region VARCHAR2(10), Sales NUMBER(7)); The normal SELECT simply queries for all the data. SELECT Year,Country,Region,Sales FROM Company_Sales ORDER BY Year,Country,Region; YEAR COUNTRY REGION 1997 France Other 1997 France Paris 1997 USA Central 1997 USA East 1997 USA West 1998 France Other 1998 France Paris 1998 USA Central 1998 USA East 1998 USA West 1999 France Other 1999 France Paris 1999 USA Central 1999 USA East 1999 USA West

SALES 1450 2540 1270 3320 8500 1520 2790 1330 3650 8920 1660 2910 1470 3830 9370

The aggregation is for each group(i.e. France in 1997, USA in 1997, France in 1998, etc.). This is standard SQL. And with the Oracle implementation of GROUP BY, the rows are returned in ascending order within the groups. This is the summarized data without totals. Report Totals (Without ROLLUP) What we have all read (and many of us have programmed) reports with subtotals and a grand total at the end. In the above example, this is a subtotal of Sales for each year and a grand total of Sales for all years at the end of the report. There are a number of ways to program this report. Following report is typical, using the query results along with a procedural language (i.e. PL/SQL, PRO*C, Java with SQLJ or JDBC) to retrieve the query rows, one-by-one, in the correct order and printing the subtotals and totals.

An Embarcadero Technologies White Paper

-2-

Report Subtotals and Totals Using Select ROLLUP in Oracle

YEAR 1997 1997 ---------------Sum of Year 1998 1998 ---------------Sum of Year 1999 1999 ---------------Sum of Year

COUNTRY France USA

France USA ----------

SALES 3990 13090 --------17080 4310 13900 --------18210 4570 14670 --------19240 --------54530

France USA ----------

Sum of all Years

The report subtotals and the grand total are the calculations we want to reproduce, in a single Select statement, with ROLLUP. The ROLLUP clause The ROLLUP clause in the SQL Select calculates subtotals and total values, just like the above rport example. The subtotals rows and the grand total row are called superaggregate rows to distinguish them from the normal query results. The ROLLUP is very simple to use, as you can see in the following query, which calculates the subtotals and the grand total. The difference is the "ROLLUP (Year,Country)" after the GROUP BY. SELECT Year,Country,SUM(Sales) AS Sales FROM Company_Sales GROUP BY ROLLUP (Year,Country); YEAR COUNTRY SALES 1997 France 3990 1997 USA 13090 1997 17080 1998 France 4310 1998 USA 13900 1998 18210 1999 France 4570 1999 USA 14670 1999 19240 54530

Thus the ROLLUP calculates superaggregrate subtotals and grand total all in one SQL statement. NULL Values in data In this simple example, the subtotals and the grand total are obvious. Since there is not any Null data, we interpret the last line as the grand total. But clean data is normally only a dream. We

An Embarcadero Technologies White Paper

-3-

Report Subtotals and Totals Using Select ROLLUP in Oracle

need to distinguish which columns are the superaggregated subtotals and the grand total column from the other data. We do this with the GROUPING() function. Look at the following: SELECT Year, Country, GROUPING(Year) AS GrpYear, GROUPING(Country) AS GrpCountry, SUM(Sales) AS Sales FROM Company_Sales GROUP BY ROLLUP (Year,Country); YEAR 1997 1997 1997 1998 1998 1998 1999 1999 1999 COUNTRY France USA France USA France USA GRPYEAR 0 0 1 0 0 1 0 0 1 1 GRPCOUNTRY 0 0 0 0 0 0 0 0 0 0 SALES 3990 13090 17080 4310 13900 18210 4570 14670 19240 54530

We can now distinguish which columns are "normal" results(without ROLLUP) from those which are superaggregrate subtotals and the grand total. The GROUPING function argument is always a column in the ROLLUP clause and always returns a one if the column is a superaggregate of the argument or zero otherwise. With GROUPING, we see these relationships: GROUPING(Year) + GROUPING(Country) = 0 - Normal Row GROUPING(Year) + GROUPING(Country) = 1 - Subtotal Row GROUPING(Year) + GROUPING(Country) = 2 - Grand Total Row

We distinguish the normal rows, subtotals and the grand total easily. When there are three or more levels in the ROLLUP (e.g. Year, Country, Product), an OR condition of the GROUPING functions is necessary to uniquely define the rows. With this relationship, we can now add column values for the subtotals ("Sum of Year") and the grand total("Sum of All Years") with the help of the DECODE function: SELECT DECODE(GROUPING(Year)+GROUPING(Country), 2,'Sum of All Years',Year) AS Year, DECODE(GROUPING(Year)+GROUPING(Country), 1,'Sum of Year',Country) AS Country, SUM(Sales) AS Sales FROM Company_Sales GROUP BY ROLLUP (Year,Country);

An Embarcadero Technologies White Paper

-4-

Report Subtotals and Totals Using Select ROLLUP in Oracle

YEAR 1997 1997 1997 1998 1998 1998 1999 1999 1999

COUNTRY France USA Sum of Year France USA Sum of Year France USA Sum of Year Sums of all years

SALES 3990 13090 17080 4310 13900 18210 4570 14670 19240 54530

The DECODE is almost an IF statement implemented as a function that recodes the values. This expression: DECODE(GROUPING(Year)+GROUPING(Country),2,'Sum of All Years',Year) Is, in pseudo code as: IF ( GROUPING(Year)+GROUPING(Country) = 2 ) THEN use 'Sum of All Years' as column value ELSE use column value for Year And for the second DECODE, the pseudo code is: IF ( GROUPING(Year)+GROUPING(Country) = 1 ) THEN use "Sum of Year' as column value ELSE use column value for Country Any NULL values will now be obvious. And we have the same results as the report example, from a single SELECT statement. Selecting only Subtotals and the Grand Total Using the GROUPING function in the HAVING clause makes it easy to select only the superaggregrate rows. SELECT DECODE(GROUPING(Year)+GROUPING(Country), 2,'Sum of All Years',Year) AS Year, DECODE(GROUPING(Year)+GROUPING(Country), 1,'Sum of Year',Country) AS Country, SUM(Sales) AS Sales FROM Company_Sales GROUP BY ROLLUP (Year,Country) HAVING GROUPING(Year) + GROUPING(Country) > 0; YEAR COUNTRY 1997 Sum of Year 1998 Sum of Year 1999 Sum of Year Sums of all years SALES 17080 18210 19240 54530

We now have only the subtotals and the grand total, without the data !! Quite nice really.

An Embarcadero Technologies White Paper

-5-

Report Subtotals and Totals Using Select ROLLUP in Oracle

The uses should be clearer now. A query can be: The "normal" data: without a GROUP BY The aggregated data: GROUP BY with summarizing function(SUM, AVG, .) The aggregated data with the superaggregrate subtotals and / or the grand total. Only the superaggregrate subtotals and/or the grand total.

In the presentation of data from Data Warehouses and Data Marts, the subtotals and the grand total can now be included in the calculation directly from the SQL Select statement. The superaggregated lines can be returned as part of the data, or they can be returned without the underlying data. Since the query is a single statement, Oracle optimizes the statement calculating the results with the fewest number of disk accesses and minimum CPU time. As a note, it is possible to calculate the same results using only SQL Select, without the ROLLUP clause and without programming. This uses several SELECTs joined by UNION ALL. These tend to be complicated to write and less efficient to execute. Extension of ROLLUP: CUBE CUBE calculates all the combinations of subtotals. In the example data, we have subtotals for each Year, but not for the other combination, subtotals for Countries. Cube calculates the same subtotals as ROLLUP plus the other subtotal combinations(subtotal for France and subtotal for USA). With several factors, the number of multi-dimension subtotals become large. Jay Wortman is an independent consultant and has lived in Paris for more than 19 years. He ran his own consulting business in Paris for a number of years and now travels around Europe by working on projects. He is an Oracle specialist(Oracle Certified DBA V7.3, V8.0 and V8.1). His favorite projects include Data Warehouse and Web applications. He speaks fluent French and fluent Java. You can contact him at wortman_j@hotmail.com. Embarcadero Technologies, Inc. is a leading provider of strategic data management solutions that help companies to improve the availability, integrity, accessibility, and security of corporate data. Nearly 12,000 customers, including 97 of the Fortune 100, rely on Embarcadero Technologies solutions to maximize their return on corporate data assets and to meet the challenges of explosive data growth, escalating data security requirements, and complex, multi-platform data environments.
Embarcadero, the Embarcadero Technologies logos and all other Embarcadero Technologies product or service names are trademarks of Embarcadero Technologies, Inc. All other trademarks are property of their respective owners.

An Embarcadero Technologies White Paper

-6-

You might also like