6.3 语法
MERGE [INTO [schema .] table [t_alias]
USING [schema .] { table | view | subquery } [t_alias]
ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
6.4 使用案例
1. 基于escore表创建escore2表,英语成绩每个同学加上5分的课时分,新增政治成绩,如下:
create table escore2 as select sid,type,score+5 score from escore where type='e'
insert into escore2 values(1,'z',31);
insert into escore2 values(2,'z',45);
insert into escore2 values(3,'z',66);
insert into escore2 values(4,'z',76);
commit;
根据escore2表更新escore表,根据sid和type匹配,对于已经存在的记录进行更新操作,对于不存在的记录进行插入操作。
merge into escore t
using escore2 t2--此处可以是表、视图和查询结果集
on (t.sid=t2.sid and t.type=t2.type)--匹配条件,需要加括号
when matched then
update set t.score=nvl(t2.score,decode(t.type,'e',5,0))--根据匹配条件,更新escore
when not matched then
insert values(t2.sid,t2.type,t2.score)--无匹配条件的记录,插入新记录
执行merge以后的escore表如下:
注意update的时候不能修改匹配的连接字段,否则就会报错。
6.5 使用场景
当要依赖别的表、视图或者结果集批量修改和插入目标表数据时,可以使用此方法,运行速率快,而且简单。
7 group by高级特性
7.1 学习目标
学会使用group by语句,学会使用group by输出小计、合计。
7.2 要点
1. 在select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚合函数返回每一个组的汇总信息。
2. 可以使用having子句限制返回的结果集。
3. 在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数语法。
4. 使用rollup操作符产生subtotal(小计)的值,cube 操作符产生cross-tabulation(列联交叉表)的值。
5. 使用grouping函数标识通过rollup和cube 建立的行的值。
6. 使用grouping sets产生一个single result set(结果集)。
7. 使用grouping_id和group_id函数。
7.3 使用案例
1. 查询部门员工的最高工资大于1500的部门,如下:
相信这样的案例大家已经很熟悉了,以下讲解一下group by的高级特性。
2. Rollup可以返回合计,例如:
rollup(a,b) 包括:(a,b)、(a)、()的合计
rollup(a,b,c) 包括:(a,b,c)、(a,b)、(a)、()的合计
我想按班级和学生分组,查询班级下学生的总分,并且做一下小计,使用以上的escore表,并且新建学生班级的关系表如下:
create table refcs as
select 1 cid,1 sid from dual
union all select 1,2 from dual
union all select 2,1 from dual
union all select 2,2 from dual
则查询的sql如下,红色区域是每个班级的总分合适,蓝色区域是所有的总分合计:
3. cube可以返回交叉的合计,例如:
cube(a,b) 包括:(a,b)、(a)、(b)、()
cube(a,b,c) 包括:(a,b,c)、(a,b)、(a,c)、(b,c)、(a)、(b)、(c)、()
与rollup相比,多了灰色区域,灰色区域是对分组的第二个字段sid的小计,用来统计每个学生的总分数,但在此是没有多大意义的,因为学生和班级是1->n的关系,统计每个学生的总分数和统计每个班级下每个学生的总分数没有区别。
4. GROUPING函数可以接受一列,返回0或者1。如果列值为空,那么GROUPING()返回1;如果列值非空,那么返回0。GROUPING只能在使用ROLLUP或CUBE的查询中使用。当需要在返回空值的地方显示某个值时,GROUPING()就非常有用。
看如下sql,红色区域和蓝色区域的grouping参数字段是null,因此grouping字段返回1,非null时返回0:
但是返回0和1似乎没有多大意义,通常返回一些有意义的字符串可读性能好一些,如下:
其实你可以再优化一下,让第一行只显示“总计”两个字。
5. Grouping sets:以上用GROUP BY ROLLUP或GROUP BY CUBE替代GROUP BY,来计算高级的统计,不过它们会生成所有可能的总数,而你可能不需要全部总数,可以用GROUP BY GROUPING SETS来代替GROUP BY CUBE。你可以应用来指定你感兴趣的总数组合。因为它不必计算它不需要集合(也不会产生太多结果),所以对SQL引擎来说更为高效。例如:
在图中我已经用不同颜色的边框和箭头指明某行数据来源于grouping sets之后的哪些集合。
7.4 使用场景
分组时常用。
8 分析函数
8.1 学习目标
掌握分析函数的使用,能用分析函数解决复杂查询等问题。
8.2 要点
1. 分析函数可分为四类:等级函数(ranking),聚合函数(aggregate),行比较函数(row comparison),统计函数(statistical)。
2.
8.3 语法
函数名(参数)over(partition by …order by…windows clause)
8.4 使用案例
1. Row_number,rank,dense_rank属于等级函数,例如,我想根据部分分区,查询部门内部员工公司的排名,看一下用这三个等级函数会有什么区别:
我们发现三个函数都是返回分区排序后的序号,不同之处在于排序字段相同时,row_number是从1到n连续不跳号的,rank是给予值相同的两行相同的序号,而且跳号,dense_rank也是给予值相同的两行同样的序号,但是不跳号。
2. 常用分析函数:看一下以下一个sql中包含了多个常用的分析函数,图中需要注意的地方我已经圈出来并且标明了:
常用的分析函数还有lag、lead、percent_rank、PERCENTILE_COUNT等,大家可以自己回去研究一下。
3. First、last返回通过dense_rank排序后的第一个或者最后一个。例如我想查询员工的最小工资最小的部门和员工的最大工资最大的部门:
4. Windows子句,用来指明分析函数的计算窗口,语法如下:
窗口的划分方式有range和rows两种,Rows 表示物理偏移量,range表示逻辑偏移量。用rows 或range划分窗口,按照起点在上