oracle rollup function with multiple columns
Solution 1
I find it rather easier to specify the exact sets I need with the GROUPING SET clause:
WITH data(val1, val2, val3) AS
( SELECT 'a' ,'a-details' ,'1' FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by grouping sets ((val1, val2),());
I suspect that it is more efficient, as it directly specifies the levels to calculate.
http://sqlfiddle.com/#!4/8301d/3
CUBE and ROLLUP are handy for generating large numbers of aggregation levels automatically (eg. every level in a dimensional hierarchy), and there might be a case for using GROUPING ID if you wanted to eliminate a small subset of levels from a large CUBE-generated set, but GROUPING SET is precisely designed for specifying particular aggregation levels.
Solution 2
GROUPING_ID Expression
You can use the GROUPING_ID
expression to filter which levels of subtotals you need:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by ROLLUP(val1, val2)
HAVING GROUPING_ID(val1, val2) IN (0, 3);
Output:
NVL(VAL1,'TOTALRESULT') VAL2 TOT ----------------------- --------- ---------- a a-details 1 b b-details 2 c c-details 3 Total Result 6
GROUPING_ID
returns 0 for rows with no subtotals, 1 for the first level and so on, we can take a look at values returned by it:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot,
GROUPING_ID(val1, val2) AS grp_id
from data
group by ROLLUP(val1, val2);
NVL(VAL1,'TOTALRESULT') VAL2 TOT GRP_ID ----------------------- --------- ---------- ---------- a a-details 1 0 a 1 1 b b-details 2 0 b 2 1 c c-details 3 0 c 3 1 Total Result 6 3
More about Rollup and related topics: Tim Hall about Rollup and Cube
(Edit)
The GROUPING Function
Regarding comment. You can use the GROUPING
function:
GROUPING - accepts a single column as a parameter and returns "1" if the column contains a null value generated as part of a subtotal by a
ROLLUP
orCUBE
operation or "0" for any other value, including stored null values.
Example of returned values:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot,
grouping(val1),
grouping(val2)
from data
group by ROLLUP(val1, val2);
Output:
NVL(VAL1,'TOTALRESULT') VAL2 TOT GROUPING(VAL1) GROUPING(VAL2) ----------------------- --------- ---------- -------------- -------------- a a-details 1 0 0 a 1 0 1 b b-details 2 0 0 b 2 0 1 c c-details 3 0 0 c 3 0 1 Total Result 6 1 1
So your query should look like:
WITH data AS
( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
UNION ALL
SELECT 'b' ,'b-details' ,'2' FROM DUAL
UNION ALL
SELECT 'c' ,'c-details' ,'3' FROM DUAL
)
SELECT NVL(val1,'Total Result'),
val2,
SUM(val3) tot
from data
group by ROLLUP(val1, val2)
HAVING GROUPING(val1) = 1
OR (GROUPING(val1) + GROUPING(val2) = 0);
Output:
NVL(VAL1,'TOTALRESULT') VAL2 TOT ----------------------- --------- ---------- a a-details 1 b b-details 2 c c-details 3 Total Result 6
Idea of using the GROUPING
function from AskTom, here.
ajmalmhd04
I am , currently hooked with Oracle; flowing with computer and the technologies since after my schools, joined for bachelors degree specialised in ǝɔuǝıɔs ɹǝʇndɯoɔ and tasted basics of the programming languages like c, c++ to java, It includes basics of perl , python, and some sharp knowledges in html and css. Before leaving from my college,I have learned some tactics with the .Net platform which include SqlServer, as backend, and languages like c# and visualbasic. And so badged another Certification on Web Applications, hence Certified as Microsoft Technology Specialist.(MCTS) My previous certifications on Graphic Designing which comprises( Photoshop,Coreldraw,Illustrator). :) My first earning came into my pocket before my college ends, on a financial year ending , I got to work in a private bank, for some data entry project and Interest calculating issues. So I used MS Access as a simple tool. My average plus typing speed above 40wpm for the data entry help alot for the earlier completion for the project. I had a little work for creating website in my current company for developing website that make use of wordpress themes and so I learned about the language in PHP, and the database MySql. As my interest is and still wandering on data and database, I moved on the database team and currently my graph is stepping on Oracle, working with sql queries and plsql. Familiarizing with the Oracle Spatial and slight insight in Sql Loader tools. SELECT chr(ajmalmhd04 +4 +50-25-12-13) ||chr(ajmalmhd04+2+150+-25+4-25+4-9+5-0-1-2) ||chr(ajmalmhd04 -3) ||chr(ajmalmhd04 +18) ||chr(ajmalmhd04 +1) ||chr(ajmalmhd04 -68) ||chr(ajmalmhd04 +2) ||chr(ajmalmhd04 +17) ||chr(ajmalmhd04 +10) ||chr(ajmalmhd04 -67) ||chr(ajmalmhd04 -10-68+5+7-2+5-3-2-3+4-3-1+3) ||chr(ajmalmhd04 -42) ||chr(ajmalmhd04 -59) FROM (SELECT 1000/10 ajmalmhd04 FROM dual)
Updated on July 09, 2022Comments
-
ajmalmhd04 almost 2 years
I've a simple query:
WITH data(val1, val2, val3) AS ( SELECT 'a' ,'a-details' ,'1' FROM DUAL UNION ALL SELECT 'b' ,'b-details' ,'2' FROM DUAL UNION ALL SELECT 'c' ,'c-details' ,'3' FROM DUAL ) SELECT NVL(val1,'Total Result'), val2, SUM(val3) tot from data group by rollup(val1, val2);
I get an output like:
VAL1 VAL2 TOT -------------------------------- -------------------------------- ---------- a a-details 1 a 1 b b-details 2 b 2 c c-details 3 c 3 Total Result 6
But I need an output like:
VAL1 VAL2 TOT -------------------------------- -------------------------------- ---------- a a-details 1 b b-details 2 c c-details 3 Total Result 6
Thanks in advance.
-
ajmalmhd04 over 10 years@Przemyslaw Kruglej, Please let me know anyway to use the query other than explicitly using
(0,3)
, as I need to change on adding columns. -
Przemyslaw Kruglej over 10 years@ajmalmhd04 I think you should accept David Aldridge's answer. I had no idea you could do it like that with
GORUPING SETS
. -
ajmalmhd04 over 10 yearsThanks @David Aldrige. So this is now a new learning topic for me.
-
ajmalmhd04 over 10 years@PrzemyslawKruglej, Thanks for both your answers. Will learn more about GROUPING. You've anyhow +1 by me :).