As cláusulas ROLLUP, CUBE e GROUPING |
A conjugação das funções de grupo com a cláusula GROUP BY permite obter contagens, somas ou médias sobre os valores dos elementos de um grupo. As cláusulas ROLLUP e CUBE permitem agregar esses resultados, produzindo contagens sobre as contagens, somas das somas ou médias das médias:
ROLLUP
A cláusula ROLLUP é usada juntamente com GROUP BY e permite agregações sobre grupos de linhas. Vamos analisar a sua utilidade seguindo uma sequência de exemplos.
Usando funções de grupo conseguimos determinar a soma de salários por função (JOB) mas, usando um único query, não conseguimos determinar também a soma total. Adicionando a cláusula ROLLUP ao GROUP BY conseguimos obter essa soma, como mostra o primeiro exemplo:
select job, sum(sal) from emp group by rollup(job) order by job; |
JOB SUM(SAL) --------- ---------------------- ANALYST 6000 CLERK 4150 MANAGER 8275 PRESIDENT 5000 SALESMAN 5600 29025 6 rows selected |
O exemplo abaixo determina a soma de salários por departamento e usa a cláusula ROLLUP para a soma total:
select deptno, sum(sal) from emp group by rollup(deptno) order by deptno; |
DEPTNO SUM(SAL) ---------------------- ---------------------- 10 8750 20 10875 30 9400 29025 4 rows selected |
Vamos complicar o problema inicial; agora pretendemos a soma de salários por função (JOB) e por departamento (DEPTNO) e vamos utilizar GROUP BY ROLLUP:
select job, deptno, sum(sal) from emp group by rollup(job,deptno) order by job, deptno; |
JOB DEPTNO SUM(SAL) --------- ---------------------- ---------------------- ANALYST 20 6000 ANALYST 6000 CLERK 10 1300 CLERK 20 1900 CLERK 30 950 CLERK 4150 MANAGER 10 2450 MANAGER 20 2975 MANAGER 30 2850 MANAGER 8275 PRESIDENT 10 5000 PRESIDENT 5000 SALESMAN 30 5600 SALESMAN 5600 29025 15 rows selected |
No quarto exemplo invertemos a ordem de GROUP BY para fazer um ROLLUP(DEPTNO,JOB):
select deptno, job, sum(sal) from emp group by rollup(deptno, job) order by deptno, job; |
DEPTNO JOB SUM(SAL) ---------------------- --------- ---------------------- 10 CLERK 1300 10 MANAGER 2450 10 PRESIDENT 5000 10 8750 20 ANALYST 6000 20 CLERK 1900 20 MANAGER 2975 20 10875 30 CLERK 950 30 MANAGER 2850 30 SALESMAN 5600 30 9400 29025 13 rows selected |
No quinto exemplo adicionamos o cálculo da média de salários e a contagem do número de empregados. Vamos fazer um GROUP BY ROLLUP(JOB, DEPTNO):
select job, deptno, sum(sal), round(avg(sal)), count(*) from emp group by rollup(job, deptno) order by job, deptno; |
JOB DEPTNO SUM(SAL) ROUND(AVG(SAL)) COUNT(*) --------- ---------------------- ---------------------- ---------------------- ---------------------- ANALYST 20 6000 3000 2 ANALYST 6000 3000 2 CLERK 10 1300 1300 1 CLERK 20 1900 950 2 CLERK 30 950 950 1 CLERK 4150 1038 4 MANAGER 10 2450 2450 1 MANAGER 20 2975 2975 1 MANAGER 30 2850 2850 1 MANAGER 8275 2758 3 PRESIDENT 10 5000 5000 1 PRESIDENT 5000 5000 1 SALESMAN 30 5600 1400 4 SALESMAN 5600 1400 4 29025 2073 14 15 rows selected |
O sexto exemplo faz as mesmas selecções que o quinto, mas alteramos a cláusula GROUP BY ROLLUP de (JOB, DEPTNO) para (DEPTNO, JOB):
select deptno, job, sum(sal), round(avg(sal)), count(*) from emp group by rollup(deptno, job) order by deptno, job; |
DEPTNO JOB SUM(SAL) ROUND(AVG(SAL)) COUNT(*) ---------------------- --------- ---------------------- ---------------------- ---------------------- 10 CLERK 1300 1300 1 10 MANAGER 2450 2450 1 10 PRESIDENT 5000 5000 1 10 8750 2917 3 20 ANALYST 6000 3000 2 20 CLERK 1900 950 2 20 MANAGER 2975 2975 1 20 10875 2175 5 30 CLERK 950 950 1 30 MANAGER 2850 2850 1 30 SALESMAN 5600 1400 4 30 9400 1567 6 29025 2073 14 13 rows selected |
A cláusula ROLLUP(coluna1, coluna2) permite fazer agregações parciais pelo par (coluna1, coluna2), agregações totais por coluna1 e as somas totais.
CUBE
A clausula CUBE é uma extensão de ROLLUP que permite as agregações totais por todas as colunas envolvidas. Na prática cria um cubo.
O exemplo abaixo determina a soma de salários usando GROUP BY CUBE(JOB, DEPTNO):
select job, deptno, sum(sal) from emp group by cube(job, deptno) order by job, deptno; |
JOB DEPTNO SUM(SAL) --------- ---------------------- ---------------------- ANALYST 20 6000 ANALYST 6000 CLERK 10 1300 CLERK 20 1900 CLERK 30 950 CLERK 4150 MANAGER 10 2450 MANAGER 20 2975 MANAGER 30 2850 MANAGER 8275 PRESIDENT 10 5000 PRESIDENT 5000 SALESMAN 30 5600 SALESMAN 5600 10 8750 20 10875 30 9400 29025 18 rows selected |
O próximo exemplo adiciona à soma de salários a média de salários e a contagem do número de empregados. Usamos GROUP BY CUBE(JOB, DEPTNO) para obter todas as agregações possíveis:
select job, deptno, sum(sal), round(avg(sal)), count(*) from emp group by cube(job, deptno) order by job, deptno; |
JOB DEPTNO SUM(SAL) ROUND(AVG(SAL)) COUNT(*) --------- ---------------------- ---------------------- ---------------------- ---------------------- ANALYST 20 6000 3000 2 ANALYST 6000 3000 2 CLERK 10 1300 1300 1 CLERK 20 1900 950 2 CLERK 30 950 950 1 CLERK 4150 1038 4 MANAGER 10 2450 2450 1 MANAGER 20 2975 2975 1 MANAGER 30 2850 2850 1 MANAGER 8275 2758 3 PRESIDENT 10 5000 5000 1 PRESIDENT 5000 5000 1 SALESMAN 30 5600 1400 4 SALESMAN 5600 1400 4 10 8750 2917 3 20 10875 2175 5 30 9400 1567 6 29025 2073 14 18 rows selected |
GROUPING
A função GROUPING pode ser usada com ROLLUP ou CUBE e serve para determinar se a linha devolvida pelo query resulta de uma agregação:
select job, deptno, sum(sal), round(avg(sal)), count(*), grouping(job), grouping(deptno) from emp group by cube(job, deptno) order by job, deptno; |
JOB DEPTNO SUM(SAL) ROUND(AVG(SAL)) COUNT(*) GROUPING(JOB) GROUPING(DEPTNO) --------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ANALYST 20 6000 3000 2 0 0 ANALYST 6000 3000 2 0 1 CLERK 10 1300 1300 1 0 0 CLERK 20 1900 950 2 0 0 CLERK 30 950 950 1 0 0 CLERK 4150 1038 4 0 1 MANAGER 10 2450 2450 1 0 0 MANAGER 20 2975 2975 1 0 0 MANAGER 30 2850 2850 1 0 0 MANAGER 8275 2758 3 0 1 PRESIDENT 10 5000 5000 1 0 0 PRESIDENT 5000 5000 1 0 1 SALESMAN 30 5600 1400 4 0 0 SALESMAN 5600 1400 4 0 1 10 8750 2917 3 1 0 20 10875 2175 5 1 0 30 9400 1567 6 1 0 29025 2073 14 1 1 18 rows selected |
A cláusula GROUPING pode beneficiar com da função CASE:
select case when grouping(deptno)=0 then to_char(deptno,'99') when grouping(job)=0 then 'Soma por função '|| job else 'Total geral' end as deptno, case when grouping(job)=0 then job when grouping(deptno)=0 then 'Soma por departamento '|| to_char(deptno,'99') else 'Total geral' end as job, sum(sal) from emp group by cube(deptno, job) order by deptno, job; |
DEPTNO JOB SUM(SAL) ------------------------- ------------------------- ---------------------- 10 CLERK 1300 10 MANAGER 2450 10 PRESIDENT 5000 10 Soma por departamento 10 8750 20 ANALYST 6000 20 CLERK 1900 20 MANAGER 2975 20 Soma por departamento 20 10875 30 CLERK 950 30 MANAGER 2850 30 SALESMAN 5600 30 Soma por departamento 30 9400 Soma por função ANALYST ANALYST 6000 Soma por função CLERK CLERK 4150 Soma por função MANAGER MANAGER 8275 Soma por função PRESIDENT PRESIDENT 5000 Soma por função SALESMAN SALESMAN 5600 Total geral Total geral 29025 18 rows selected |
Realizado por Turtle Learning ®. Última alteração em 2011-02-26