rollup相對於簡單的分組合計增長了小計和合計(適用於統計功能),解釋起來會比較抽象,下面咱們來看看具體事例。函數
select deptno,sum(sal) from emp group by deptno with rollup;
select deptno,job,sum(sal) from emp group by deptno,job with rollup;
這裏可能就有人會有疑問了,爲何數據比原來多了10條,理論上應該只是所有的總結,只會比group by 多一條數據才合理,查了資料才弄明白,對於聚合單數據(group by 後面的變量一個爲單數據,多個則爲多數據)是適合的,可是在多數據的狀況下就不同了,下面咱們分析一下,首先會根據depno變量,將原始數據分爲9個101,102,103...109九個組,group by WITH ROLLUP會在每一個分組後面加上本組類的信息(deptno),第5行數據就是1,2,3,4行數據聚合所執行sum(sal)所得的結果,依次類推...108,109也是同樣,同時在最後,會將所有的分組聚合。性能
性能分析:測試
#實現單個部門,單個工種的工資的總和 select deptno,job,sum(sal) from emp group by deptno,job union all #實現單個部門工資的總和 select deptno,null,sum(sal) from emp group by deptno union all #實現全部部門工資的總和 select null,null,sum(sal) from emp order by deptno desc,job desc
性能分析:spa
經過2,3執行結果的性能分析:不難看出,相同的功能實現,ROLLUP相對於UNION ALL效率有了極大的提高。code
#emp 表結構 CREATE TABLE `emp` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `empno` mediumint(8) unsigned NOT NULL DEFAULT '0', `ename` varchar(20) NOT NULL DEFAULT '', `job` varchar(9) NOT NULL DEFAULT '', `mgr` mediumint(8) unsigned NOT NULL DEFAULT '0', `hiredate` date NOT NULL, `sal` decimal(7,2) NOT NULL, `comm` decimal(7,2) NOT NULL, `deptno` mediumint(8) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=500001 DEFAULT CHARSET=utf8;
#常規處理 select deptno,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno
#1.使用 union all select deptno,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno union all select null ,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp #2.使用 rollup select deptno,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno with rollup;
1. 這個記錄沒有出現總計兩個字,怎麼實現呢? 使用 ifnull()函數 (有坑)blog
#有坑版 select ifnull(deptno,'彙總') deptno,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno with rollup; #爲何說有坑? 若是deptno 自己爲null ,那麼以上查詢將會出現多個彙總行。 #填坑版 (使用雙層ifnull判斷 or 將字段定義爲not null) select ifnull(deptno,'彙總') deptno,dev_sal,manager_sal,salesman_sal,Test_sal from ( select ifnull(deptno,'空城(默認)') deptno,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno ) a group by deptno with rollup;
#天真的處理方式 select ifnull(deptno,'空城(默認)') deptno,sum(if(job = 'dev',sal,null)) dev_sal,sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal,sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno with rollup ORDER BY Test_sal ; #結果報錯: Incorrect usage of CUBE/ROLLUP and ORDER BY #緣由:MySQL 雖然提供了 group by with rollup 函數進行group by 字段的彙總,but 與 order by 互斥,不能同時用 #正確方式 使用order by field() #根據測試崗位的Test_sal薪資降序排列 總計置於底部 =>能夠把上面代碼當成一個子表嵌套 結合 order by field()自定義函數實現 select *from ( select ifnull(deptno,'總計') deptno,dev_sal,manager_sal,salesman_sal,Test_sal from ( select ifnull(deptno,'空城(默認)') deptno,sum(if(job = 'dev',sal,null)) dev_sal, sum(if(job = 'manager',sal,null)) manager_sal,sum(if(job = 'salesman',sal,null)) salesman_sal, sum(if(job = 'Test',sal,null)) Test_sal from emp group by deptno )a group by deptno with rollup ) b ORDER BY FIELD(b.deptno,'總計'),b.Test_sal DESC;