Предложение GROUPING SETS
может упростить код и повысить производительность нескольких комбинаций групп.
Более простой код
Для примера давайте начнем с простой таблицы:
create table t1(a number, b number, c number, d number);
insert into t1
select 0,0,0,0 from dual union all
select 1,0,0,0 from dual union all
select 0,1,0,0 from dual union all
select 1,1,0,0 from dual union all
select 0,0,1,0 from dual union all
select 1,0,1,0 from dual union all
select 0,1,1,0 from dual union all
select 1,1,1,0 from dual union all
select 0,0,0,1 from dual union all
select 1,0,0,1 from dual union all
select 0,1,0,1 from dual union all
select 1,1,0,1 from dual union all
select 0,0,1,1 from dual union all
select 1,0,1,1 from dual union all
select 0,1,1,1 from dual union all
select 1,1,1,1 from dual;
Приведенный ниже запрос представляет группировку по «A & (B | C)». (В отличие от вашего примера, я собираюсь включить несколько пустых столбцов, чтобы продемонстрировать, как работает группировка.)
select a, b, null c, count(*)
from t1
group by a, b
union all
select a, null b, c, count(*)
from t1
group by a, c;
A B C COUNT(*)
- - - --------
1 0 4
0 0 4
1 1 4
0 1 4
1 0 4
0 0 4
1 1 4
0 1 4
Переписывание с GROUPING SETS
создает те же результаты, что и предыдущий запрос:
select a, b, c, count(*)
from t1
group by grouping sets((a, b), (a, c));
Лучшая производительность
Выполнение вышеуказанных запросов с использованием explain plan for ...
и затем select * from table(dbms_xplan.display(format => 'basic'));
возвращает следующие планы выполнения.
Для UNION ALL
версии:
------------------------------------
| Id | Operation | Name |
------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | UNION-ALL | |
| 2 | HASH GROUP BY | |
| 3 | TABLE ACCESS FULL| T1 |
| 4 | HASH GROUP BY | |
| 5 | TABLE ACCESS FULL| T1 |
------------------------------------
Для GROUPING SETS
версии:
-------------------------------------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TEMP TABLE TRANSFORMATION | |
| 2 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6787_464CF95 |
| 3 | TABLE ACCESS FULL | T1 |
| 4 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6788_464CF95 |
| 5 | HASH GROUP BY | |
| 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6787_464CF95 |
| 7 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6788_464CF95 |
| 8 | HASH GROUP BY | |
| 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6787_464CF95 |
| 10 | VIEW | |
| 11 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6788_464CF95 |
-------------------------------------------------------------------------------
План выполнения UNION ALL
считывает из исходной таблицы один раз для каждой отдельной группировки. План выполнения GROUPING SETS
читает только из исходной таблицы только один раз, сохраняет информацию во временной таблице, а затем читает из этой временной таблицы.
Если в запросе используется только небольшое подмножество строк или только небольшое подмножество столбцов, план GROUPING SETS
может быть значительно быстрее, поскольку он должен прочитать полные данные только один раз.