SQL语句——08聚集,分组,行转列
Posted marxist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL语句——08聚集,分组,行转列相关的知识,希望对你有一定的参考价值。
常用聚集函数
是对一组或一批数据进行综合操作后返回一个结果,如下:
count | 行总数 |
avg | 平均数 |
sum | 列值和 |
max | 最大值 |
min | 最小值 |
用法说明
count([{distinct|all} \'列名\'|*) 为列值时空不在统计之内,为*时包含空行和重复行
idle> select count(comm) from emp;
COUNT(COMM)
-----------
4
idle> select count(ename) from emp;
COUNT(ENAME)
------------
14
idle> select count(*) from emp;
COUNT(*)
----------
14
idle> select count(deptno) from emp;
COUNT(DEPTNO)
-------------
14
idle> select count(distinct deptno) from emp;
COUNT(DISTINCTDEPTNO)
---------------------
3
idle> select count(all deptno) from emp;
COUNT(ALLDEPTNO)
----------------
14
上面执行的聚集函数都是对所有记录统计,如果想分组统计(比如统计部门的平均值)需要使用group by,为了限制分组统计的结果需要使用having过滤
求出每个部门的平均工资
idle> select deptno,avg(sal) from emp group by deptno;
DEPTNO AVG(SAL)
---------- ----------
30 1566.66667
20 2175
10 2916.66667
分组再排序
idle> select deptno,avg(sal) from emp group by deptno order by deptno ;
DEPTNO AVG(SAL)
---------- ----------
10 2916.66667
20 2175
30 1566.66667
分组修饰列可以是未选择的列
idle> select avg(sal) from emp group by deptno order by deptno;
AVG(SAL)
----------
2916.66667
2175
1566.66667
如果在查询中使用了分组函数,任何不在分组函数中的列或表达式必须在group by子句中。因为分组函数是返回一行而其他列显示多行显示结果矛盾。
idle> select avg(sal) from emp ;
AVG(SAL)
----------
2073.21429
idle> select deptno,avg(sal) from emp;
select deptno,avg(sal) from emp
*
ERROR at line 1:
ORA-00937: not a single-group group function
idle> select deptno,avg(sal) from emp group by deptno ;
DEPTNO AVG(SAL)
---------- ----------
30 1566.66667
20 2175
10 2916.66667
idle> select deptno,avg(sal) from emp group by deptno order by job;
select deptno,avg(sal) from emp group by deptno order by job
*
ERROR at line 1:
ORA-00979: not a GROUP BY expression
group by 的过滤
查出平均工资大于2000的部门
idle> select deptno,avg(sal) avg from emp group by deptno where avg >2000;
select deptno,avg(sal) avg from emp group by deptno where avg >2000
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
group by后不能再接where子句过滤,where过滤只能加到group by前端这样又不能满足要求,对分组后的过滤要使用having。
idle> select deptno,avg(sal) avg from emp group by deptno having avg(sal) >2000;
DEPTNO AVG
---------- ----------
20 2175
10 2916.66667
分组函数的注意事项:
- 分组函数只能出现在select,order by,having,分析函数子句中
- 分组函数会忽略NULL 除了count(*)
- 分组函数中可以使用ALL或distinct;ALL是默认值,统计所有。加上distinct则只统计不同
- 如果选择的列里有普通列,表达式和分组列,那么普通列和表达式都必须出现在group by中 。
如下操作:得到t5表中有部分行是重复的,找出重复的行
SQL> create table t5 as select * from emp;
Table created.
SQL> insert into t5 select * from emp where deptno=20;
5 rows created.
SQL> commit;
Commit complete.
SQL>
查看:
select count(ename),ename from t5 group by ename having COUNT(ENAME) !=1;
删除: 不是函数,而是列名
delete t5 where rowid in (select max(rowid) from t5 group by ename having count(ename)>1);
行转列
pivot(行专列)and unpivot(列转行)函数的使用
pivot(聚合函数 for 列名 in(类型)) ,其中 in(‘’) 中可以指定别名,in中还可以指定子查询,
比如 select distinct code from customers
select * from (select name, nums from demo) pivot (sum(nums) for name in (\'苹果\', \'橘子\', \'葡萄\', \'芒果\'));
select id , name, jidu, xiaoshou from Fruit unpivot (xiaoshou for jidu in (q1, q2, q3, q4) )
注意:unpivot没有聚合函数,xiaoshou、jidu字段也是临时的变量
普通方式
create table t4(id int,name varchar2(10),subject varchar2(20),grade number); insert into t4 values(1,\'ZORRO\',\'语文\',70); insert into t4 values(2,\'ZORRO\',\'数学\',80); insert into t4 values(3,\'ZORRO\',\'英语\',75); insert into t4 values(4,\'SEKER\',\'语文\',65); insert into t4 values(5,\'SEKER\',\'数学\',75); insert into t4 values(6,\'SEKER\',\'英语\',60); insert into t4 values(7,\'BLUES\',\'语文\',60); insert into t4 values(8,\'BLUES\',\'数学\',90); insert into t4 values(9,\'PG\',\'数学\',80); insert into t4 values(10,\'PG\',\'英语\',90); commit; SQL> select * from t4; ID NAME SUBOBJECT GRADE ---------- ---------- -------------------- ---------- 1 ZORRO 语文 70 2 ZORRO 数学 80 3 ZORRO 英语 75 4 SEKER 语文 65 5 SEKER 数学 75 6 SEKER 英语 60 7 BLUES 语文 60 8 BLUES 数学 90 9 PG 数学 80 10 PG 英语 90 10 rows selected. SQL> select name,max(case subobject when \'语文\' then grade else 0 end) “语文”, max(case subobject when \'数学\' then grade else 0 end) "数学", max(case subobject when \'英语\' then grade else 0 end) "英语" from t4 group by name; ---------------------------- | name | 语文 | 数学| 英语| ---------------------------- | zorro | 70 | 80 | 75 | ---------------------------- | seker | 65 | 75 | 60 | ---------------------------- | blues | 60 | 90 | 0 | ---------------------------- | PG | 0 | 80 | 90 | ----------------------------
以上是关于SQL语句——08聚集,分组,行转列的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 动态行转列(参数化表名分组列行转列字段字段值)