在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
代码
create table testScore
(
tid int primary key identity(1,1),
tname varchar(30) null,
ttype varchar(10) null,
tscor int null
)
go
---插入数据 insert into testScore values (\'张三\',\'语文\',80)
insert into testScore values (\'张三\',\'数学\',98)
insert into testScore values (\'张三\',\'英语\',65)
insert into testScore values (\'李四\',\'语文\',70)
insert into testScore values (\'李四\',\'数学\',80)
insert into testScore values (\'李四\',\'英语\',90)
select tname as \'姓名\' ,
max(case ttype when \'语文\' then tscor else 0 end) \'语文\',
max(case ttype when \'数学\' then tscor else 0 end) \'数学\',
max(case ttype when \'英语\' then tscor else 0 end) \'英语\'
from testScore
group by tname
实例二
有如下数据:(为了看得更清楚,我并没有使用国家代码,而是直接用国家名作为Primary Key)
国家(country) | 人口(population) |
中国 | 600 |
美国 | 100 |
加拿大 | 100 |
英国 | 200 |
法国 | 300 |
日本 | 250 |
德国 | 200 |
墨西哥 | 50 |
印度 | 250 |
根据这个国家人口数据,统计亚洲和北美洲的人口数量。应该得到下面这个结果。
洲 | 人口 |
亚洲 | 1100 |
北美洲 | 250 |
其他 | 700 |
代码
SELECT SUM(population),
CASE country
WHEN \'中国\' THEN \'亚洲\'
WHEN \'印度\' THEN \'亚洲\'
WHEN \'日本\' THEN \'亚洲\'
WHEN \'美国\' THEN \'北美洲\'
WHEN \'加拿大\' THEN \'北美洲\'
WHEN \'墨西哥\' THEN \'北美洲\'
ELSE \'其他\' END
FROM Table_A
GROUP BY CASE country
WHEN \'中国\' THEN \'亚洲\'
WHEN \'印度\' THEN \'亚洲\'
WHEN \'日本\' THEN \'亚洲\'
WHEN \'美国\' THEN \'北美洲\'
WHEN \'加拿大\' THEN \'北美洲\'
WHEN \'墨西哥\' THEN \'北美洲\'
ELSE \'其他\' END;
同样的,我们也可以用这个方法来判断工资的等级,并统计每一等级的人数。SQL代码如下;
SELECT
CASE WHEN salary <= 500 THEN \'1\'
WHEN salary > 500 AND salary <= 600 THEN \'2\'
WHEN salary > 600 AND salary <= 800 THEN \'3\'
WHEN salary > 800 AND salary <= 1000 THEN \'4\'
ELSE NULL END salary_class,
COUNT(*)
FROM Table_A
GROUP BY
CASE WHEN salary <= 500 THEN \'1\'
WHEN salary > 500 AND salary <= 600 THEN \'2\'
WHEN salary > 600 AND salary <= 800 THEN \'3\'
WHEN salary > 800 AND salary <= 1000 THEN \'4\'
ELSE NULL END;
对于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 |
代码
SELECT country,
SUM( CASE WHEN sex = \'1\' THEN
population ELSE 0 END), --男性人口 SUM( CASE WHEN sex = \'2\' THEN
population ELSE 0 END) --女性人口FROM Table_A
GROUP BY country;
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表中查询至少有两位教师的系及教师人数。
实现代码:
SELECT DNAME, COUNT(*) AS num_teacher
FROM TEACHER
GROUP BY DNAME
HAVING COUNT(*)>=2
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?