我会使用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仍然有一个表扫描一个更好的计划。
使用ROLLUP可获得更好的性能。如果需要通过group by子句使用小计。请参阅http://sql-plsql.blogspot.in/2010/10/rollup。html –