Использование CUBE и ROLLUP отметок в SQL (Oracle 11g)
Применение отметок(опций) CUBE и ROLLUP во фразе GROUP BY запроса позволяет производить функционально более полные операции суммирования. CUBE и ROLLUP предоставляют информацию, которую в ином случае можно можно было получить только посредством дополнительных запросов или кодирования.
Следующий запрос показывает "нормальную" функциональность GROUP BY. Оператор SQL сортирует детальные данные, используя столбцы, указанные в GROUP BY, затем вычисляет результаты - одна строка для каждой группы :
Select e.department_id,e.job_id, SUM(e.salary) sum_s
From hr.employees e
Group by e.department_id,e.job_id;
From hr.employees e
Group by e.department_id,e.job_id;
Результат:
DEPARTMENT_ID | JOB_ID | SUM_S |
---|---|---|
110 | AC_ACCOUNT | 8300 |
90 | AD_VP | 34000 |
50 | ST_CLERK | 55700 |
80 | SA_REP | 243500 |
50 | ST_MAN | 36400 |
80 | SA_MAN | 61000 |
110 | AC_MGR | 12008 |
90 | AD_PRES | 24000 |
60 | IT_PROG | 28800 |
100 | FI_MGR | 12008 |
30 | PU_CLERK | 13900 |
50 | SH_CLERK | 64300 |
20 | MK_MAN | 13000 |
100 | FI_ACCOUNT | 39600 |
SA_REP | 7000 | |
70 | PR_REP | 10000 |
30 | PU_MAN | 11000 |
10 | AD_ASST | 4400 |
20 | MK_REP | 6000 |
40 | HR_REP | 6500 |
ROLLUP строит агрегаты-подитоги (subtotal aggregates) на каждом запрошенном уровне, включая окончательный итог (grand total):
Select e.department_id,e.job_id, SUM(e.salary) sum_s
From hr.employees e
Group by ROLLUP(e.department_id,e.job_id);
From hr.employees e
Group by ROLLUP(e.department_id,e.job_id);
Результат:
DEPARTMENT_ID | JOB_ID | SUM_S |
---|---|---|
SA_REP | 7000 | |
7000 | ||
10 | AD_ASST | 4400 |
10 | 4400 | |
20 | MK_MAN | 13000 |
20 | MK_REP | 6000 |
20 | 19000 | |
30 | PU_MAN | 11000 |
30 | PU_CLERK | 13900 |
30 | 24900 | |
40 | HR_REP | 6500 |
40 | 6500 | |
50 | ST_MAN | 36400 |
50 | SH_CLERK | 64300 |
50 | ST_CLERK | 55700 |
50 | 156400 | |
60 | IT_PROG | 28800 |
60 | 28800 | |
70 | PR_REP | 10000 |
70 | 10000 | |
80 | SA_MAN | 61000 |
80 | SA_REP | 243500 |
80 | 304500 | |
90 | AD_VP | 34000 |
90 | AD_PRES | 24000 |
90 | 58000 | |
100 | FI_MGR | 12008 |
100 | FI_ACCOUNT | 39600 |
100 | 51608 | |
110 | AC_MGR | 12008 |
110 | AC_ACCOUNT | 8300 |
110 | 20308 | |
691416 |
-подитоги (subtotals). Сумма каждой группы e.department_id.
-окончательный итог(grand total).Общая сумма.
CUBE автоматически вычисляет все возможные комбинации возможных подитогов, включая окончательный итог(grand total):
Select e.department_id,e.job_id, SUM(e.salary) sum_s
From hr.employees e
Group by CUBE(e.department_id,e.job_id);
From hr.employees e
Group by CUBE(e.department_id,e.job_id);
Результат:
DEPARTMENT_ID | JOB_ID | SUM_S |
---|---|---|
7000 | ||
691416 | ||
AD_VP | 34000 | |
AC_MGR | 12008 | |
FI_MGR | 12008 | |
HR_REP | 6500 | |
MK_MAN | 13000 | |
MK_REP | 6000 | |
PR_REP | 10000 | |
PU_MAN | 11000 | |
SA_MAN | 61000 | |
SA_REP | 7000 | |
SA_REP | 250500 | |
ST_MAN | 36400 | |
AD_ASST | 4400 | |
AD_PRES | 24000 | |
IT_PROG | 28800 | |
PU_CLERK | 13900 | |
SH_CLERK | 64300 | |
ST_CLERK | 55700 | |
AC_ACCOUNT | 8300 | |
FI_ACCOUNT | 39600 | |
10 | 4400 | |
10 | AD_ASST | 4400 |
20 | 19000 | |
20 | MK_MAN | 13000 |
20 | MK_REP | 6000 |
30 | 24900 | |
30 | PU_MAN | 11000 |
30 | PU_CLERK | 13900 |
40 | 6500 | |
40 | HR_REP | 6500 |
50 | 156400 | |
50 | ST_MAN | 36400 |
50 | SH_CLERK | 64300 |
50 | ST_CLERK | 55700 |
60 | 28800 | |
60 | IT_PROG | 28800 |
70 | 10000 | |
70 | PR_REP | 10000 |
80 | 304500 | |
80 | SA_MAN | 61000 |
80 | SA_REP | 243500 |
90 | 58000 | |
90 | AD_VP | 34000 |
90 | AD_PRES | 24000 |
100 | 51608 | |
100 | FI_MGR | 12008 |
100 | FI_ACCOUNT | 39600 |
110 | 20308 | |
110 | AC_MGR | 12008 |
110 | AC_ACCOUNT | 8300 |
-подитоги (subtotals). Сумма каждой группы e.department_id.
-подитоги (subtotals). Сумма каждой группы
e.job_id.
-итоги (grand total).Общая сумма.
Для того, чтобы улучшить обработку NULL-значений в строках, созданных ROLLUP и CUBE , используют функцию GROUPING, которая возвращает значение 1, если строка - это подитог, созданная ROLLUP или CUBE, и 0 в противном случае:
Select e.department_id,e.job_id, SUM(e.salary) sum_s,GROUPING(e.job_id)
From hr.employees e
Group by CUBE(e.department_id,e.job_id);
From hr.employees e
Group by CUBE(e.department_id,e.job_id);