如何在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 ;

输出结果

播放器
title_type
total_titles
罗杰·费德勒
ATP巡回赛冠军
103
罗杰·费德勒
大满贯
20
罗杰·费德勒
 
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;

输出结果

播放器
title_type
total_titles
安德烈·阿加西(Andre Agassi)
ATP巡回赛冠军
52
安德烈·阿加西(Andre Agassi)
大满贯
8
安德烈·阿加西(Andre Agassi)
 
60
安迪·穆雷(Andy Murray)
ATP巡回赛冠军
46
安迪·穆雷(Andy Murray)
大满贯
3
安迪·穆雷(Andy Murray)
 
49
安迪·罗迪克
ATP巡回赛冠军
32
安迪·罗迪克
大满贯
0
安迪·罗迪克
 
32
德约科维奇(Novak Djokovic)
ATP巡回赛冠军
81
德约科维奇(Novak Djokovic)
大满贯
17
德约科维奇(Novak Djokovic)
 
98
皮特·桑普拉斯
ATP巡回赛冠军
64
皮特·桑普拉斯
大满贯
14
皮特·桑普拉斯
 
78
拉斐尔·纳达尔(Rafael Nadal)
ATP巡回赛冠军
86
拉斐尔·纳达尔(Rafael Nadal)
大满贯
20
拉斐尔·纳达尔(Rafael Nadal)
 
106
罗杰·费德勒
ATP巡回赛冠军
103
罗杰·费德勒
大满贯
20
罗杰·费德勒
 
123
托马斯·穆斯特(Thomas Muster)
ATP巡回赛冠军
39
托马斯·穆斯特(Thomas Muster)
大满贯
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;

输出结果

播放器
title_type
total_titles
安德烈·阿加西(Andre Agassi)
ATP巡回赛冠军
52
安德烈·阿加西(Andre Agassi)
大满贯
8
安德烈·阿加西(Andre Agassi)
 
60
安迪·穆雷(Andy Murray)
ATP巡回赛冠军
46
安迪·穆雷(Andy Murray)
大满贯
3
安迪·穆雷(Andy Murray)
 
49
安迪·罗迪克
ATP巡回赛冠军
32
安迪·罗迪克
大满贯
0
安迪·罗迪克
 
32
德约科维奇(Novak Djokovic)
ATP巡回赛冠军
81
德约科维奇(Novak Djokovic)
大满贯
17
德约科维奇(Novak Djokovic)
 
98
皮特·桑普拉斯
ATP巡回赛冠军
64
皮特·桑普拉斯
大满贯
14
皮特·桑普拉斯
 
78
拉斐尔·纳达尔(Rafael Nadal)
ATP巡回赛冠军
86
拉斐尔·纳达尔(Rafael Nadal)
大满贯
20
拉斐尔·纳达尔(Rafael Nadal)
 
106
罗杰·费德勒
ATP巡回赛冠军
103
罗杰·费德勒
大满贯
20
罗杰·费德勒
 
123
托马斯·穆斯特(Thomas Muster)
ATP巡回赛冠军
39