在oracle里 group by 分组是怎么回事 为啥有时候不加group by说不是单组分组函数?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在oracle里 group by 分组是怎么回事 为啥有时候不加group by说不是单组分组函数?相关的知识,希望对你有一定的参考价值。
概述今天主要分享下Oracle数据库分组函数group by 、 rollup、cude、grouping 、grouping sets的常用用法,以下以Oracle自带schema做演示。
1、group by的使用
--根据DEPTNO和JOB进行分组。求相同DEPTNO,相同JOB的员工工资总和。
SELECT E.DEPTNO,E.JOB,SUM(E.SAL) FROM EMP E GROUP BY E.DEPTNO,E.JOB ORDER BY E.DEPTNO;
2、group by 配合rollup的使用
rollup()--可以使用一个或者多个参数。意思是从右向左进行数据的汇总统计,并生成一行,rollup是个统计函数。
以下是根据分组情况进行统计,最终进行全部汇总。
(1)简单的使用rollup--生成一行新数据。(要生成新的一行数据,还可以使用UNION ALL)
SELECT D.DUMMY FROM DUAL D GROUP BY ROLLUP(D.DUMMY);
(2)先根据E.DEPTNO,E.JOB进行分组,然后从右向左
SELECT E.DEPTNO,E.JOB,SUM(E.SAL) FROM EMP E GROUP BY ROLLUP(E.DEPTNO,E.JOB) ORDER BY E.DEPTNO;
针对以上的使用ROLLUP的结果的理解:
a:首先根据GROUP BY E.DEPTNO,E.JOB查询出9条数据(除4,8,12,13外),在根据rollup的定义,从右向左,对ROLLUP中的参数进行小计
首先根据JOB(对所有的JOB进行汇总),汇总出4,8,12行,在根据E.DEPTNO(对所有的DEPTNO进行汇总),汇总出第十三行数据。
(3) 特殊情况
SELECT E.DEPTNO,E.JOB,SUM(E.SAL) FROM EMP E GROUP BY ROLLUP(E.JOB,E.DEPTNO) ORDER BY E.DEPTNO;
理解:首先根据GROUP BY E.DEPTNO,E.JOB查询出前九条数据,其次对E.DEPTNO进行汇总,但是必须考虑JOB,也就是相同的JOB,的所有的工资总和,所以出现下面五条数据。
3、group by 配合cube的使用
SELECT E.DEPTNO,E.JOB,SUM(E.SAL) FROM EMP E GROUP BY CUBE(E.DEPTNO,E.JOB) ORDER BY E.DEPTNO;
理解:CUBE会对条件中的每一个条件进行单独的汇总:即对单独的列进行汇总
GROUP BY CUBE(E.DEPTNO,E.JOB)首先根据:GROUP BY E.DEPTNO,E.JOB查询数据,其次对E.JOB进行汇总(不考虑DEPTNO,单独汇总,而ROLLUP是在同一个DEPTNO下面)再对E.DEPTNO进行汇总,最后全部汇总。
cube(a,b) 统计列包含:(a,b)、(a)、(b)、()
cube(a,b,c) 统计列包含:(a,b,c)、(a,b)、(a,c)、(b,c)、(a)、(b)、(c)、()
4、GROUPING 的使用
GROUPING函数可以接受一列,返回0或者1。如果列值为空,那么GROUPING()返回1;如果列值非空,那么返回0。GROUPING只能在使用ROLLUP或CUBE的查询中使用。当需要在返回空值的地方显示某个值时,GROUPING()就非常有用。
SELECT GROUPING(E.DEPTNO), E.DEPTNO,E.JOB,SUM(E.SAL) FROM EMP E GROUP BY ROLLUP(E.DEPTNO,E.JOB) ORDER BY E.DEPTNO;
可以使用decode或者case函数进行转换这种不友好的显示:
SELECT
CASE WHEN grouping(E.DEPTNO) = 1
THEN '总计'
ELSE E.DEPTNO || ''
END AS 部门,
CASE WHEN grouping(E.JOB) = 1 AND grouping(E.DEPTNO) = 0
THEN '小计'
ELSE E.JOB
END AS 工作种类,
SUM(E.SAL) FROM EMP E GROUP BY ROLLUP(E.DEPTNO,E.JOB)
ORDER BY E.DEPTNO;
SELECT DECODE(GROUPING(E.DEPTNO), 1, '总计', E.DEPTNO) AS 部门,
CASE
WHEN GROUPING(E.JOB) = 1 AND GROUPING(E.DEPTNO) = 0 THEN
'小计'
ELSE
E.JOB
END AS 工作种类,
SUM(E.SAL)
FROM EMP E
GROUP BY ROLLUP(E.DEPTNO, E.JOB)
ORDER BY E.DEPTNO;
5、grouping sets提供了指定汇总集合条件的功能
根据E.DEPTNO,E.JOB分别汇总数据。
SELECT E.DEPTNO,E.JOB,SUM(E.SAL) FROM EMP E GROUP BY GROUPING SETS(E.DEPTNO,E.JOB);
觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~ 参考技术A 比如你选一个表的总汇总,比如有一个员工表,里面有员工号,部门号,薪资。
然后你想查所有员工的总薪资,那么使用聚合函数SUM来完成,可是你想想,这个需要分组么?返回结果只有一行,就是表所有行的汇总,所以不需要分组。
而同样这个表,查询每个部门的总薪资,就要按照部门分组了,因为查询的结果是一个部门一行。
GROUP BY肯定是要和聚合函数一起使用的,但是,使用聚合函数,未必就一定分组,因为查询表所有行当中的汇总,或者最大,或者最小值等等,这些是不需要分组的。本回答被提问者和网友采纳 参考技术B 首先要知道什么是单组分组函数 。 像:sum(),count(),avg()等等 这样做运算的函数 是单组分组函数。
而在使用group by的时候 ,group by 后面添加的字段是所有出现在select 子句中不是这些函数的字段。
比如:
select sum(sal),deptno from emp group by deptno
是算出各部门的总工资数
select ename,deptno from emp group by ename,deptno
如果select子句中没有包含任何函数,那么group by后面添加的字段是所有出现在select 子句中不是这些函数的字段。 参考技术C 当你的查询语句中有聚合函数(max,min,count,sum)时,就需要用到goup by 分组了。
Oracle_group by分组查询_深入
Oracle_group by分组查询_深入
在SQL Server中使用的分组查询是ORDER BY子句,使用ORDER BY子句要同聚合函数配合使用才能完成分组查询,在SELECT查询的字段中如果字段没有使用聚合函数就必须出现在ORDER BY子句中(即SELECT后边的字段名要么出现在聚合函数中,要么在ORDER BY子句中使用)
在分组查询中还可以配合使用HAVING子句,定义查询条件。
使用group by进行分组查询
在使用group by关键字时,在select列表中可以指定的项目是有限制的,select语句中仅许以下几项:
〉被分组的列
〉为每个分组返回一个值得表达式,例如用一个列名作为参数的聚合函数
group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面(重要)
group by实例
实例一
数据表:
姓名 科目 分数
张三 语文 80
张三 数学 98
张三 英语 65
李四 语文 70
李四 数学 80
李四 英语 90
期望查询结果:
姓名 语文 数学 英语
张三 80 98 65
李四 70 80 90
代码
![](https://image.cha138.com/20210513/a37120adaf1e4dfbaf437953daf0f9bd.jpg)
![](https://image.cha138.com/20210513/1fdfa0f952124021a0675382a6cd07d8.jpg)
create table testScore
![](https://image.cha138.com/20210513/dbfe683fd4b14f7caa9cf736043e3e9e.jpg)
(
![](https://image.cha138.com/20210513/c58316d013064995b075b01a7f57995b.jpg)
tid int primary key identity(1,1),
![](https://image.cha138.com/20210513/a1307e803a844c3bb9bbb9a91574c1df.jpg)
tname varchar(30) null,
![](https://image.cha138.com/20210513/eb225bdafa0346c3803f15aceb88511d.jpg)
ttype varchar(10) null,
![](https://image.cha138.com/20210513/97604887dc81449287466c99869a4ea1.jpg)
tscor int null
![](https://image.cha138.com/20210513/089576421ee6451e82441b021802b436.jpg)
)
![](https://image.cha138.com/20210513/e54f377f72eb4af982a22bade736948f.jpg)
go
![](https://image.cha138.com/20210513/26e977e2f2ee454cb7b48b0846e662e0.jpg)
---插入数据insert into testScore values (\'张三\',\'语文\',80)
![](https://image.cha138.com/20210513/70cf600128c54d5ca88c8046d2a38cb2.jpg)
insert into testScore values (\'张三\',\'数学\',98)
![](https://image.cha138.com/20210513/5473958602134d8e9337d696f85591ee.jpg)
insert into testScore values (\'张三\',\'英语\',65)
![](https://image.cha138.com/20210513/be4010dc829a4c5b82194bc24a53bebc.jpg)
insert into testScore values (\'李四\',\'语文\',70)
![](https://image.cha138.com/20210513/7f59b35ce1114cb095c2cf49921f5555.jpg)
insert into testScore values (\'李四\',\'数学\',80)
![](https://image.cha138.com/20210513/329ce745b69c47e9be82e05643ba2ace.jpg)
insert into testScore values (\'李四\',\'英语\',90)
![](https://image.cha138.com/20210513/914a5135f47a410a914b3be5d7c1ff65.jpg)
![](https://image.cha138.com/20210513/e4aef1a3927e4feca357aeede6325641.jpg)
![](https://image.cha138.com/20210513/635aef47eb3340a8a3a048cc53b14d2d.jpg)
select tname as \'姓名\' ,
![](https://image.cha138.com/20210513/642b6804031745c19bfa42c101ec14c6.jpg)
max(case ttype when \'语文\' then tscor else 0 end) \'语文\',
![](https://image.cha138.com/20210513/ff6f8831ffdc433db236ad7f4f89e1f7.jpg)
max(case ttype when \'数学\' then tscor else 0 end) \'数学\',
![](https://image.cha138.com/20210513/c8f6cd2828524389985965b85094dde8.jpg)
max(case ttype when \'英语\' then tscor else 0 end) \'英语\'
![](https://image.cha138.com/20210513/a3c90650aa4c407fb181d80e92c62661.jpg)
from testScore
![](https://image.cha138.com/20210513/78002c5a1788473d8b77b5756530dd40.jpg)
group by tname
![](https://image.cha138.com/20210513/86242c3b098742b793f28a29f4019c6d.jpg)
实例二
有如下数据:(为了看得更清楚,我并没有使用国家代码,而是直接用国家名作为Primary Key)
国家(country) | 人口(population) |
中国 | 600 |
美国 | 100 |
加拿大 | 100 |
英国 | 200 |
法国 | 300 |
日本 | 250 |
德国 | 200 |
墨西哥 | 50 |
印度 | 250 |
根据这个国家人口数据,统计亚洲和北美洲的人口数量。应该得到下面这个结果。
洲 | 人口 |
亚洲 | 1100 |
北美洲 | 250 |
其他 | 700 |
代码
![](https://image.cha138.com/20210513/f504ec2868ee45379d21484bcab74123.jpg)
![](https://image.cha138.com/20210513/b259fa1c641f4866a89c4a31b99d726c.jpg)
SELECT SUM(population),
![](https://image.cha138.com/20210513/7280e6d5ea2c4be2bc346e0e1e005f32.jpg)
CASE country
![](https://image.cha138.com/20210513/231699103b244417904dcb8c1306134e.jpg)
WHEN \'中国\' THEN \'亚洲\'
![](https://image.cha138.com/20210513/c649df490a3b4247b31dd4b837762527.jpg)
WHEN \'印度\' THEN \'亚洲\'
![](https://image.cha138.com/20210513/7266a5c69a2f4fb2a7b5dc97e1af5ae8.jpg)
WHEN \'日本\' THEN \'亚洲\'
![](https://image.cha138.com/20210513/3995929e46ea4fd58977c27ce2ac70d8.jpg)
WHEN \'美国\' THEN \'北美洲\'
![](https://image.cha138.com/20210513/854e7f1dfd9e4dcf80f4858597841610.jpg)
WHEN \'加拿大\' THEN \'北美洲\'
![](https://image.cha138.com/20210513/7a8a778f49194032acff669a033475ea.jpg)
WHEN \'墨西哥\' THEN \'北美洲\'
![](https://image.cha138.com/20210513/6a90ea14f4f24423824c70fe81fa3297.jpg)
ELSE \'其他\' END
![](https://image.cha138.com/20210513/87e5750540544810b691be627a7a27d1.jpg)
FROM Table_A
![](https://image.cha138.com/20210513/ff75df3e68684e8da682946fbdcf5dcb.jpg)
GROUP BY CASE country
![](https://image.cha138.com/20210513/47bbaa34636845ed8ddad54783165fd7.jpg)
WHEN \'中国\' THEN \'亚洲\'
![](https://image.cha138.com/20210513/86b9c18515e9490a91bf9de1e4617419.jpg)
WHEN \'印度\' THEN \'亚洲\'
![](https://image.cha138.com/20210513/e12b4a26e6464fb9a1c42da3ee1b6e17.jpg)
WHEN \'日本\' THEN \'亚洲\'
![](https://image.cha138.com/20210513/9a9450f043244014bb9909c1c3e44515.jpg)
WHEN \'美国\' THEN \'北美洲\'
![](https://image.cha138.com/20210513/204954abcbf34870885df202575c89df.jpg)
WHEN \'加拿大\' THEN \'北美洲\'
![](https://image.cha138.com/20210513/5474df6e3fab45adb9e87d56c0597427.jpg)
WHEN \'墨西哥\' THEN \'北美洲\'
![](https://image.cha138.com/20210513/5232f530b2b94d078e658ad007ce3b08.jpg)
ELSE \'其他\' END;
![](https://image.cha138.com/20210513/bafef1521d444baa96a2e77186d2b7ee.jpg)
同样的,我们也可以用这个方法来判断工资的等级,并统计每一等级的人数。SQL代码如下;
![](https://image.cha138.com/20210513/9ed5909939f84330963278bb77fdbfb9.jpg)
![](https://image.cha138.com/20210513/45e7ed7547c84730a4357dcce82aa494.jpg)
SELECT
![](https://image.cha138.com/20210513/691997b474244db38fdc8651b97585a0.jpg)
CASE WHEN salary <= 500 THEN \'1\'
![](https://image.cha138.com/20210513/80d2a3e432b546a9831ffd2e0b5d1b66.jpg)
WHEN salary > 500 AND salary <= 600 THEN \'2\'
![](https://image.cha138.com/20210513/49efcb3a0f684c7b8c5b9b7a65b56cdc.jpg)
WHEN salary > 600 AND salary <= 800 THEN \'3\'
![](https://image.cha138.com/20210513/a8fcb30703424b0bb17ee291cf2ba8e5.jpg)
WHEN salary > 800 AND salary <= 1000 THEN \'4\'
![](https://image.cha138.com/20210513/8109019d7b764e98ade29225d264da95.jpg)
ELSE NULL END salary_class,
![](https://image.cha138.com/20210513/a4541158dbbc484887008392154486ce.jpg)
COUNT(*)
![](https://image.cha138.com/20210513/e97f5378080c4ef4aa2a2190d1d3abe1.jpg)
FROM Table_A
![](https://image.cha138.com/20210513/169b3cb3345a464f99d402e51426712a.jpg)
GROUP BY
![](https://image.cha138.com/20210513/040453a56ee741cfb19f85ac3b11c804.jpg)
CASE WHEN salary <= 500 THEN \'1\'
![](https://image.cha138.com/20210513/79f18f5044f5435289677930f6406fa7.jpg)
WHEN salary > 500 AND salary <= 600 THEN \'2\'
![](https://image.cha138.com/20210513/cacdaf7e9cfe4492b3da8609c18f6da0.jpg)
WHEN salary > 600 AND salary <= 800 THEN \'3\'
![](https://image.cha138.com/20210513/e10a758177274fbc9c8e7b12715dfcf7.jpg)
WHEN salary > 800 AND salary <= 1000 THEN \'4\'
![](https://image.cha138.com/20210513/9f83f9391c6543dba9dee9baa66b29a0.jpg)
ELSE NULL END;
![](https://image.cha138.com/20210513/7a72c1cb161545db932c6772f6af6dd3.jpg)
对于groupby后面一般都是跟一个列名,但在该例子中通过case语句使分组变得跟强大了。
实例三
有如下数据
国家(country) | 性别(sex) | 人口(population) |
中国 | 1 | 340 |
中国 | 2 | 260 |
美国 | 1 | 45 |
美国 | 2 | 55 |
加拿大 | 1 | 51 |
加拿大 | 2 | 49 |
英国 | 1 | 40 |
英国 | 2 | 60 |
按照国家和性别进行分组,得出结果如下
国家 | 男 | 女 |
中国 | 340 | 260 |
美国 | 45 | 55 |
加拿大 | 51 | 49 |
英国 | 40 | 60 |
代码
![](https://image.cha138.com/20210513/faacdc120b30476e8ea3ae6841e14192.jpg)
![](https://image.cha138.com/20210513/4d5d95eee2e74620b6005c4986266fa5.jpg)
SELECT country,
![](https://image.cha138.com/20210513/6d2fbc26fdcf466c8ed1cd6becffe544.jpg)
SUM( CASE WHEN sex = \'1\' THEN
![](https://image.cha138.com/20210513/4b6da88c2a844cb8b8586f93c74df7a2.jpg)
population ELSE 0 END), --男性人口SUM( CASE WHEN sex = \'2\' THEN
![](https://image.cha138.com/20210513/c26e43424cf74e359d8b347f991c0729.jpg)
population ELSE 0 END) --女性人口FROM Table_A
![](https://image.cha138.com/20210513/8c77387f448b46c1bc516dd1cdbaca83.jpg)
GROUP BY country;
![](https://image.cha138.com/20210513/b6fb01837f0b41b6a31a12dee3d9ddbc.jpg)
GROUP BY子句中的NULL值处理
当GROUP BY子句中用于分组的列中出现NULL值时,将如何分组呢?SQL中,NULL不等于NULL(在WHERE子句中有过介绍)。然而,在GROUP BY子句中,却将所有的NULL值分在同一组,即认为它们是“相等”的。
HAVING子句
GROUP BY子句分组,只是简单地依据所选列的数据进行分组,将该列具有相同值的行划为一组。而实际应用中,往往还需要删除那些不能满足条件的行组,为了实现这个功能,SQL提供了HAVING子句。语法如下。
SELECT column, SUM(column)
FROM table
GROUP BY column
HAVING SUM(column) condition value
说明:HAVING通常与GROUP BY子句同时使用。当然,语法中的SUM()函数也可以是其他任何聚合函数。DBMS将HAVING子句中的搜索条件应用于GROUP BY子句产生的行组,如果行组不满足搜索条件,就将其从结果表中删除。
HAVING子句的应用
从TEACHER表中查询至少有两位教师的系及教师人数。
实现代码:
![](https://image.cha138.com/20210513/722bd5db9ca34c93a738bb6758749dc3.jpg)
SELECT DNAME, COUNT(*) AS num_teacher
![](https://image.cha138.com/20210513/7820ae94e1654cfd993eb5869b5fae5e.jpg)
FROM TEACHER
![](https://image.cha138.com/20210513/deff176b68cd4cef897e35cf7afbc1c5.jpg)
GROUP BY DNAME
![](https://image.cha138.com/20210513/6468a2bab5e741ff91d08b35dd236fdc.jpg)
HAVING COUNT(*)>=2![](https://image.cha138.com/20210513/12b3a88f903e4ebda48dd172ce770947.jpg)
HAVING子句与WHERE子句的区别
HAVING子句和WHERE子句的相似之处在于,它也定义搜索条件。但与WHERE子句不同,HAVING子句与组有关,而不是与单个的行有关。
1、如果指定了GROUP BY子句,那么HAVING子句定义的搜索条件将作用于这个GROUP BY子句创建的那些组。
2、如果指定WHERE子句,而没有指定GROUP BY子句,那么HAVING子句定义的搜索条件将作用于WHERE子句的输出,并把这个输出看作是一个组。
3、如果既没有指定GROUP BY子句也没有指定WHERE子句,那么HAVING子句定义的搜索条件将作用于FROM子句的输出,并把这个输出看作是一个组。
4、在SELECT语句中,WHERE和HAVING子句的执行顺序不同。在本书的5.1.2节介绍的SELECT语句的执行步骤可知,WHERE子句只能接收来自FROM子句的输入,而HAVING子句则可以接收来自GROUP BY子句、WHERE子句和FROM子句的输入。
以上是关于在oracle里 group by 分组是怎么回事 为啥有时候不加group by说不是单组分组函数?的主要内容,如果未能解决你的问题,请参考以下文章
oracle中,还是不甚明白order by和group by的用法
SQL如何先用group by分组,并将分组的结果distinct?