SQL知识点梳理
2017-07-22 09:22
267 查看
第十八章 SQL进阶
1.0 分析函数提供一系列比较高级的SQL功能。分析函数时建立在数据窗口(over在一定的数据库范 围进行数据分析),在一定的数据范围进行排序、汇总等
select ENAME,SAL,DEPT.DEPTNO, AVG(SAL) OVER (PARTITION BY DEPT.DEPTNO) DEPT_AVG, MAX(SAL) OVER (PARTITION BY DEPT.DEPTNO) DEPT_MAX, MIN(SAL) OVER (PARTITION BY DEPT.DEPTNO) DEPT_MIN FROM EMP,DEPT WHERE EMP.DEPTNO=DEPT.DEPTNO
查询当前员工所在部门的平均工资、最高工资和最低工资,即可通过分析函数来实现
1.1 三种排序函数的使用
select dept.dname,emp.ename,emp.sal, RANK() OVER(PARTITION BY DEPT.DEPTNO ORDER BY SAL) SAL_RANK, DENSE_RANK() OVER(PARTITION BY DEPT.DEPTNO ORDER BY SAL) SAL_DENSE_RANK, ROW_NUMBER() OVER(PARTITION BY DEPT.DEPTNO ORDER BY SAL) SAL_ROW_NUMBER FROM EMP,DEPT WHERE EMP.DEPTNO=DEPT.DEPTNO
RANK是跳跃排序,dense_rank 是连续排序,两个第三名,仍然跟着第四名,row_number是没有重复
1.2数据库闪回机制
delete from emp where empno=7521
SELECT * FROM emp AS OF TIMESTAMP SYSDATE-30/(24*60) WHERE empno = 7521;
闪回至30min之前,还未删掉数据empno=7521
2.0 全局临时表
在不同的回话之间可以屏蔽数据,可以有触发器, 检查约束,索引等。比如在程序的执行过程的当前回话中需要临时存放一些数据,这些数据是其 他回话无法访问的,此时全局临时表就是一个很好的方案
2.1 on commit preserve rows是创建会话级临时表,当我们断开连接或手动执行DELETE或TRUNCATE之前,临时表中的数据一直存在,并且只有当前会话可以看到,其他会话看不到。
create global temporary table session_temp_tab on commit preserve rows as select * from emp where 1=2
2.2 ON COMMIT DELETE ROWS语句指定所创建的临时表是事务级临时表,当COMMIT或ROLLBACK之前,这些数据一直存在,当事务提交之后,表中数据自动清除。
create global temporary table transaction_temp_tab on commit delete rows as select * from emp where 1=2
插入数据,及查询数据
insert into session_temp_tab select * from emp; insert into transaction_temp_tab select * from emp; select count(*) from session_temp_tab ; select count(*) from transaction_temp_tab ;
执行一次commit操作,再次查询数据
当COMMIT之后事务级临时表中的数据自动清除,所以再次查询的时候得到结果为0
log off操作,再次查询两个表中的数据,均查不到表的信息。
3.0 物化视图
物化视图使用的也比较普遍,是一种特殊的物理表,有别于普通的数据视图。在一段时间内保存 固定的数据,提供自动刷新和手动刷新的机制。
CREATE MATERIALIZED VIEW materialized_view_name BUILD [IMMEDIATE|DEFERRED] --1. 创建方式 REFRESH [COMPLETE|FAST|FORCE|NEVER] --2. 物化视图刷新方式 ON [COMMIT|DEMAND] --3. 刷新触发方式 START WITH (start_date) --4. 开始时间 NEXT (interval_date) --5. 间隔时间 WITH [PRIMARY KEY|ROWID] --6. 默认
primary key ENABLE QUERY REWRITE --7. 是否启用查询重写 AS --8. 关键字 SELECT STATEMENT; --9. 基表选取数据的 select 语句例:
create materialized view mv_materialized_test refresh force on demand start with sysdate next to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),'20:30:00'),'dd-mm-yyyy hh24:mi:ss') as select * from emp;
每天20:30做更新
4.0 容易错用的几个函数
SELECT length('中国') FROM dual;--字符2 SELECT lengthb('中国') FROM dual;--字4 SELECT substr('上海汉得', 2, 2) FROM dual; --海汉 SELECT substr('上海汉得', 3, 2) FROM dual; --汉得 SELECT substrb('上海汉得', 2, 2) FROM dual; --空值 SELECT substrb('上海汉得', 3, 2) FROM dual; --海length是字符个数,lengthb指的是字节数。 substr是按字来取值,substrb是按字节来取值
5.0 VPD 全称Virtual Private Database,这个技术提供了对数据库信息的细粒度访问控制。 是数据库层面的一种非常成熟的数据访问控制技术,通过策略函数来实现的具体的控制
这一章节暂时弄不明白,希望大神指点,有待后续深入实践学习
第十七章 insert增强
1.0 插入增强
一个来源可插入其他目标表中,不限于一个目标表,注意:列(关键字)是一定要有所对应的
无条件的插入:
insert all into emp_temp values(empno,ename,job,mgr,hiredate,sal,comm,deptno) select * from emp where deptno=30;
有条件的插入:
insert all when job='SALESMAN' THEN INTO emp_temp values(empno,ename,job,mgr,hiredate,sal,comm,deptno) select * from emp where deptno=30;感悟:WHERE和when是可以互相转换的
inser first和insert all的区别:
insert FIRST when job='CLERK' THEN INTO emp_temp values(empno,ename,job,mgr,hiredate,sal,comm,deptno) when deptno=20 THEN INTO emp_temp_20 values(empno,ename,job,mgr,hiredate,sal,comm,deptno) select * from emp select* from emp_temp_20
insert first 指首次匹配即跳至下一条,即使后面的when条件满足,也不会再做插入
INSERT ALL 和insert first的区别:一条已经插入过when 1 条件的元组信息不会再插入 WHEN 2(即使满足when 2 中的条件)
2.0 列转行
下所示是一字符串表
使用wm_concat 函数,进行列的合并结果如下:
<clob>字符型大型对象,wm_concat行转列默认逗号隔开,也可使用其他字符作为分隔符
pivot列转行:
CREATE TABLE fruit ( ident number, fruit_name varchar2(10) not null, nums number(2) );
INSERT INTO FRUIT VALUES(1,'apple',200); INSERT INTO FRUIT VALUES(2,'apple',500); INSERT INTO FRUIT VALUES(3,'orange',300); INSERT INTO FRUIT VALUES(4,'orange',200); INSERT INTO FRUIT VALUES(5,'grape',200); INSERT INTO FRUIT VALUES(6,'grape',200);
使用pivot函数:
select * from (select fruit_name, nums from fruit) pivot(sum(nums) for fruit_name in('apple', 'orange', 'grape'))
对emp表使用行转列操作
select * from (select deptno, sal,job from emp) pivot(sum(sal) for job in('CLERK', 'SALESMAN', 'PRESIDENT', 'MANAGER', 'ANALYST'))
行转列也可以使用decode函数来操作
select deptno, sum(decode(job,'CLERK',sal)) a, sum(decode(job,'SALESMAN',sal)) b, sum(decode(job,'PRESIDENT',sal)) c, sum(decode(job,'MANAGER',sal)) d, sum(decode(job,'ANALYST',sal)) e from emp group by deptno order by deptno
unpivot函数列转行
create table Fruit_Sale( ID_NUM NUMBER, FRUIT_NAME VARCHAR2(10), Q1 NUMBER, Q2 NUMBER, Q3 NUMBER, Q4 NUMBER); INSERT INTO Fruit_Sale VALUES(1,'apple',1000,4000,3433,5000); INSERT INTO Fruit_Sale VALUES(2,'orange',1000,4000,3433,5000); INSERT INTO Fruit_Sale VALUES(3,'orange',1000,4000,3433,5000); INSERT INTO Fruit_Sale VALUES(4,'grape',1000,4000,3433,5000); INSERT INTO Fruit_Sale VALUES(5,'grape',1000,4000,3433,5000);
使用行转列将季度作为纵轴:
select ID_NUM, FRUIT_NAME, SEASON, SALES FROM Fruit_Sale UNPIVOT(SALES FOR SEASON IN(Q1, Q2, Q3, Q4))
UNPIVOT没有聚合函数,seasons和sales也是临时变量
第十六章 递归查询
emp表中MGR和empno构成递归关系
select ename || ' reports to ' || prior ename ---ename的上级 from emp start with ename='KING' CONNECT BY PRIOR EMPNO=mgr; --empno的上级是mgr,从上往下查询从‘KING’开始往下级的员工
CONNECT BY PRIOR mgr = empno --mgr的下级是empno 从下往上遍历
使用level关键字和lpad函数,在output中显示树形层次:
select lpad(ename, length(ename) + level * 2 - 2, '_') from emp start with ename = 'KING' CONNECT BY prior EMPNO = MGR
第十五章 子查询进阶
1.0 非相关子查询作为一张表
select emp.ename,emp.ename, emp.deptno,temp.salavg from emp,(select deptno, avg(sal) salavg from emp group by deptno ) temp where emp.deptno=temp.deptno and emp.sal>temp.salavg;
查询大于部门平均薪资的员工信息及部门平均薪资(非相关子查询的select可以单独执行)
1.1相关子查询:子查询中参考了外部主查询中的表(相对非相关子查询,相关子查询的select语句不能单独执行)
select ename, sal, deptno from emp outer where sal > (select avg(sal) from emp where deptno = outer.deptno);
2.1 exists操作
select empno,ename,job,deptno from emp outer where exists(select 'X' from emp where mgr=outer.empno)
查询各主管的信息
2.2 in操作
select empno, ename, job, deptno from emp outer where empno in (select mgr from emp)
查询各主管的信息
注意:如果not in子句里面存在空值,查询会出错,需要加上where ** is not null做限定,参考下例:
插入一条部门为空的emp信息
INSERT INTO EMP VALUES (8753,'SINNA','CLERK',7902,to_date('17-05-1982','dd-mm-yyyy'),800,NULL,NULL);插入一条额外部门号的信息
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
查询额外的部门信息
SELECT DEPT.DEPTNO, DEPT.DNAME FROM DEPT WHERE DEPT.DEPTNO NOT IN (SELECT DEPTNO FROM EMP)
查询结果:
添加上where department_id is not null:
SELECT DEPT.DEPTNO, DEPT.DNAME FROM DEPT WHERE DEPT.DEPTNO NOT IN (SELECT DEPTNO FROM EMP WHERE DEPTNO IS NOT NULL)
3 with子句
with dept_sal as ( select D.DNAME,SUM(E.SAL) AS DEPT_TOTAL FROM EMP E,DEPT D WHERE E.DEPTNO=D.DEPTNO GROUP BY D.DNAME ), AVG_SAL AS ( SELECT SUM(DEPT_TOTAL)/COUNT(*) as dept_avg from dept_sal ) select * from dept_sal where dept_total>(select dept_avg from AVG_SAL) order by dname
这个子句应该功能很强大,有待后续继续深入学习研究,应该可以改写大部分select子句的操作
第十四单元 group by子句增强
1.0 在Group By 中使用Rollup 产生常规分组汇总行 以及分组小计
select job,deptno,sum(sal) from emp group by rollup(job,deptno)
rollup分组和字断顺序有关,Rollup 后面跟了n个字段,就将进行n+1次分组,从右到左每次减少一个字段进行分组;然后进行 union
1.2 在Group By 中使用Cube 产生Rollup结果集 + 多维度的交叉表数据源
select job,deptno,sum(sal) from emp group by cube(job,deptno)
Cube 后面跟了n个字段,就将进行2的N次方的分组运算,和参数字段顺序没有关系
1.3 使用grouping函数判断是否被group到
select job,deptno,sum(sal), grouping(job) job_group, grouping(deptno) deptno_group from emp group by cube(job,deptno)
1.4 使用grouping set来代替多次UNION
select deptno, job, MGR,sum(sal) from emp group by grouping sets((deptno, job),(job, mgr))
有待更新,是怎么代替union子句的?
相关文章推荐
- sql知识点简单梳理
- [独孤九剑]Oracle知识点梳理(四)SQL语句之DML和DDL
- 面试宝典之知识点梳理
- jvm知识点简单梳理
- 面向对象知识点梳理(三)
- Android 知识点梳理
- 计算机组成原理知识点梳理(一)
- Android应用开发知识点总结梳理(一)
- JAVA基础知识点梳理四:数组
- PL/SQL知识点总结
- 工作中小知识点汇总(sql)
- 10分钟梳理css知识点
- C++知识点梳理——vector
- SQL知识点总结
- 非常全面的 Android Bitmap 知识点梳理
- Python爬虫知识点梳理 推荐
- Memcache知识点梳理
- 枚举类与注解的知识点梳理与代码演示
- Memcache知识点梳理
- JAVA基础知识点梳理十一:Java中的常用类