为了清晰和性能,我会使用ROLLUP。
假设你有一个这样的示例表:
create table payments (business_status_name, pending_items, datagroup) as (
select 'PROCESSING DATA', 10, 'PRODUCT' from dual union all
select 'PROCESSING DATA', 5, 'PRODUCT' from dual union all
select 'PROCESSING DATA', 2, 'SERVICE' from dual union all
select 'PROCESSING INS', 10, 'SERVICE' from dual union all
select 'PROCESSING INS', 10, 'SERVICE' from dual union all
select 'PROCESSING INS', 10, 'PRODUCT' from dual
)
这是ROLLUP的一种方式(注意括号改变分组逻辑):
SELECT BUSINESS_STATUS_NAME,
SUM(PENDING_ITEMS) as PENDING_ITEMS,
DATAGROUP
FROM PAYMENTS
GROUP BY ROLLUP ((BUSINESS_STATUS_NAME, DATAGROUP))
结果:
BUSINESS_STATUS PENDING_ITEMS DATAGRO
--------------- ------------- -------
PROCESSING INS 10 PRODUCT
PROCESSING INS 20 SERVICE
PROCESSING DATA 15 PRODUCT
PROCESSING DATA 2 SERVICE
47
计划:
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 186 | 4 (25)| 00:00:01 |
| 1 | SORT GROUP BY ROLLUP| | 6 | 186 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL | PAYMENTS | 6 | 186 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
这是UNION ALL:
SELECT BUSINESS_STATUS_NAME,
SUM(PENDING_ITEMS) as PENDING_ITEMS,
DATAGROUP
FROM PAYMENTS
GROUP BY BUSINESS_STATUS_NAME, DATAGROUP
UNION ALL
SELECT NULL, SUM(PENDING_ITEMS), NULL
FROM PAYMENTS;
结果和ROLLUP一样:
BUSINESS_STATUS PENDING_ITEMS DATAGRO
--------------- ------------- -------
PROCESSING INS 20 SERVICE
PROCESSING INS 10 PRODUCT
PROCESSING DATA 15 PRODUCT
PROCESSING DATA 2 SERVICE
47
计划不太好,用TWO FULL SCANS:
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 199 | 7 (58)| 00:00:01 |
| 1 | UNION-ALL | | | | | |
| 2 | HASH GROUP BY | | 6 | 186 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| PAYMENTS | 6 | 186 | 3 (0)| 00:00:01 |
| 4 | SORT AGGREGATE | | 1 | 13 | | |
| 5 | TABLE ACCESS FULL| PAYMENTS | 6 | 78 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
这当然只是一个小例子,有几条记录,没有索引,......所以实际表上的情况可能会有所不同,但我仍然相信ROLLUP 应该比UNION ALL 表现更好。
在更简单的情况下,与您的情况完全一样,这将是两种方法的计划:
SELECT BUSINESS_STATUS_NAME,
SUM(PENDING_ITEMS) as PENDING_ITEMS,
DATAGROUP
FROM PAYMENTS
GROUP BY ROLLUP ((BUSINESS_STATUS_NAME, DATAGROUP))
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 62 | 4 (25)| 00:00:01 |
| 1 | SORT GROUP BY ROLLUP| | 2 | 62 | 4 (25)| 00:00:01 |
| 2 | TABLE ACCESS FULL | PAYMENTS | 2 | 62 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
SELECT BUSINESS_STATUS_NAME,
PENDING_ITEMS,
DATAGROUP
FROM PAYMENTS
UNION ALL
SELECT NULL,
SUM(PENDING_ITEMS),
NULL
FROM PAYMENTS
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 75 | 6 (50)| 00:00:01 |
| 1 | UNION-ALL | | | | | |
| 2 | TABLE ACCESS FULL | PAYMENTS | 2 | 62 | 3 (0)| 00:00:01 |
| 3 | SORT AGGREGATE | | 1 | 13 | | |
| 4 | TABLE ACCESS FULL| PAYMENTS | 2 | 26 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
ROLLUP 仍然有一个更好的计划,使用单表扫描。