如何在 Oracle 中生成组小计和总计?
问题描述:
您想在 Oracle 中计算总计、小计和总计。
解决方案:
Oracle ROLLUP 函数在多个级别执行分组,使用从右到左的方法,通过中间级别向上滚动到任何总计。为了演示 ROLLUP 函数,我们将创建一个表来保存网球运动员以及该运动员获得的 ATP 巡回赛冠军和大满贯冠军。
我们将首先创建满足此需求所需的数据。
示例
-- Drop table DROP TABLE atp_titles; -- Create table CREATE TABLE atp_titles ( player VARCHAR2(100) NOT NULL, title_type VARCHAR2(100) NOT NULL, titles NUMBER NOT NULL);
示例
-- insert ATP tour titles won by the player INSERT INTO atp_titles VALUES('Roger Federer','ATP Tour Titles',103); INSERT INTO atp_titles VALUES('Rafael Nadal','ATP Tour Titles',86); INSERT INTO atp_titles VALUES('Novak Djokovic','ATP Tour Titles',81); INSERT INTO atp_titles VALUES('Pete Sampras','ATP Tour Titles',64); INSERT INTO atp_titles VALUES('Andre Agassi','ATP Tour Titles',52); INSERT INTO atp_titles VALUES('Andy Murray','ATP Tour Titles',46); INSERT INTO atp_titles VALUES('Thomas Muster','ATP Tour Titles',39); INSERT INTO atp_titles VALUES('Andy Roddick','ATP Tour Titles',32);
示例
-- insert grandslam titles won by the player INSERT INTO atp_titles VALUES('Roger Federer','Grandslams',20); INSERT INTO atp_titles VALUES('Rafael Nadal','Grandslams',20); INSERT INTO atp_titles VALUES('Novak Djokovic','Grandslams',17); INSERT INTO atp_titles VALUES('Pete Sampras','Grandslams',14); INSERT INTO atp_titles VALUES('Andre Agassi','Grandslams',8); INSERT INTO atp_titles VALUES('Andy Murray','Grandslams',3); INSERT INTO atp_titles VALUES('Thomas Muster','Grandslams',1); INSERT INTO atp_titles VALUES('Andy Roddick','Grandslams',0); COMMIT;
现在我们来看看插入到 atp_titles 表中的几条记录。
示例
SELECT * FROM atp_titles ORDER BY 1;
输出
Andre Agassi ATP Tour Titles 52 Andre Agassi Grandslams 8 Andy Murray Grandslams 3 Andy Murray ATP Tour Titles 46 Andy Roddick ATP Tour Titles 32 Andy Roddick Grandslams 0 ............................ ............................
Oracle ROLLUP 表达式会从右到左生成组小计以及总计。假设我们想利用以上数据来确定球员"罗杰·费德勒"所获得的总冠军数(即 ATP 巡回赛冠军数 + 大满贯冠军数)。
示例
SELECT player,title_type, SUM(titles) AS total_titles FROM atp_titles WHERE player = 'Roger Federer' GROUP BY ROLLUP (player,title_type) ORDER BY player,title_type ;
输出
player | title_type | total_titles |
Roger Federer | ATP Tour Titles | 103 |
Roger Federer | Grandslams | 20 |
Roger Federer | | 123 |
| | 123 |
ROLLUP 函数会为 ROLLUP 函数中列出的"n"列生成 n+1 级小计。在上面的例子中,在按球员和 title_type 进行常规分组后,ROLLUP 函数会汇总所有 title_type 值,以便我们可以看到球员"Roger Federer"的大满贯等级总和。您可以在输出中看到以粗体显示的汇总行。
现在,我们将对表格中的所有球员应用 ROLLUP 函数,如下所示:
SQL:
示例
SELECT player, title_type, SUM(titles) As total FROM atp_titles GROUP BY ROLLUP (player,title_type) ORDER BY player,title_type;
输出
player | title_type | total_titles |
Andre Agassi | ATP Tour Titles | 52 |
Andre Agassi | Grandslams | 8 |
Andre Agassi | | 60 |
Andy Murray | ATP Tour Titles | 46 |
Andy Murray | Grandslams | 3 |
Andy Murray | | 49 |
Andy Roddick | ATP Tour Titles | 32 |
Andy Roddick | Grandslams | 0 |
Andy Roddick | | 32 |
Novak Djokovic | ATP Tour Titles | 81 |
Novak Djokovic | Grandslams | 17 |
Novak Djokovic | | 98 |
Pete Sampras | ATP Tour Titles | 64 |
Pete Sampras | Grandslams | 14 |
Pete Sampras | | 78 |
Rafael Nadal | ATP Tour Titles | 86 |
Rafael Nadal | Grandslams | 20 |
Rafael Nadal | | 106 |
Roger Federer | ATP Tour Titles | 103 |
Roger Federer | Grandslams | 20 |
Roger Federer | | 123 |
Thomas Muster | ATP Tour Titles | 39 |
Thomas Muster | Grandslams | 1 |
Thomas Muster | | 40 |
| | 586 |
ROLLUP 函数允许我们执行部分汇总,以减少计算小计的次数。以下部分汇总的输出如下所示:
SQL:
示例
SELECT player, title_type, SUM(titles) As total FROM atp_titles GROUP BY ROLLUP (player,title_type) ORDER BY player,title_type;
输出
player | title_type | total_titles |
Andre Agassi | ATP Tour Titles | 52 |
Andre Agassi | Grandslams | 8 |
Andre Agassi | | 60 |
Andy Murray | ATP Tour Titles | 46 |
Andy Murray | Grandslams | 3 |
Andy Murray | | 49 |
Andy Roddick | ATP Tour Titles | 32 |
Andy Roddick | Grandslams | 0 |
Andy Roddick | | 32 |
Novak Djokovic | ATP Tour Titles | 81 |
Novak Djokovic | Grandslams | 17 |
Novak Djokovic | | 98 |
Pete Sampras | ATP Tour Titles | 64 |
Pete Sampras | Grandslams | 14 |
Pete Sampras | | 78 |
Rafael Nadal | ATP Tour Titles | 86 |
Rafael Nadal | Grandslams | 20 |
Rafael Nadal | | 106 |
Roger Federer | ATP Tour Titles | 103 |
Roger Federer | Grandslams | 20 |
Roger Federer | | 123 |
Thomas Muster | ATP Tour Titles | 39 |