您的位置:首页 > 数据库

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子句的?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息