我會使用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 –