1、行列转换

oracle 中的行列转换是通过 decode 函数实现的:

decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值);

举例:查询emp表中的每个部门的人数?

SELECT sum(decode(deptno,10,1,0)) as 部门10,
sum(decode(deptno,20,1,0)) as 部门20,
sum(decode(deptno,30,1,0)) as 部门30 from emp

做个对比

select deptno,count(deptno) from emp group by deptno

2、递归查询的优化

# 解释:字符不够的时候向左或者向右填充。
lpad/rpad( string, padded_length, [ pad_string ] )
# 输出: xxxxxabcde
select lpad('abcde',10,'x') from dual;
SELECT ID, FATHER_ID, NAME, CONNECT_BY_ISLEAF LEAF
FROM T_TREE
START WITH FATHER_ID = 0
CONNECT BY PRIOR ID = FATHER_ID;

解释:CONNECT_BY_ISLEAF 判断该行记录是否为叶子节点,如果是返回1,否则返回0

START WITH FATHER_ID = 0 规定哪一条记录为根节点

CONNECT BY PRIOR ID = FATHER_ID 判断此节点的父节点是哪一条记录

3、分析函数

分析函数是什么?

分析函数是 Oracle 专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值。

分析函数和聚合函数的不同之处是什么?

普通的聚合函数用 group by 分组,每个分组返回一个统计值,返回的字段名只能是分组名。而分析函数采用partition by分组,并且每组每行都可以返回一个统计值,返回的字段名可以是每个字段,因为是对应到记录的,所以没有关系。

分析函数的形式

分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(order by), 窗口(rows) ,他们的使用形式如下:

over(partition by xxx order by yyy rows between zzz)

窗口就是分析函数分析时要处理的数据范围,就拿 sum 来说,它是 sum 窗口中的记录而不是整个分组中的记录,因此我们在想得到某个栏位的累计值时,我们需要把窗口指定到该分组中的第一行数据到当前行, 如果你指定该窗口从该分组中的第一行到最后一行,那么该组中的每一个sum值都会一样,即整个组的总和。

OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW):当前组第一行到当前行的汇总
OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING):当前行到最后一行的汇总
OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN 1 PRECEDING AND CURRENT ROW):当前行的上一行(rownum-1)到当前行的汇总
OVER(PARTITION BY DEPTNO ORDER BY ENAME ROWS BETWEEN 1 PRECEDING AND 2 FOLLOWING):当前行的上一行(rownum-1)到下两行(rownum+2)的汇总 

tips:

1、窗口子句不能单独出现,必须有order by子句时才能出现。

2、当省略窗口子句时

a)  如果存在 order by 则默认的窗口是 unbounded preceding and current row  --当前组的第一行到当前行,即在当前组中,第一行到当前行,这里强调一下,如果 partition by 字段和 order by 字段一样的话,这个 order by不生效,相当于省略了 order by。

b)  如果同时省略 order by 则默认的窗口是 unbounded preceding and unbounded following  --整个组

SQL 中 order by 和 开窗函数 order by 的执行时机?

分析函数(以及与其配合的开窗函数over())是在整个sql查询结束后(sql语句中的order by的执行比较特殊)再进行的操作, 也就是说 sql 语句中的 order by 也会影响分析函数的执行结果:

a) 两者一致:如果sql语句中的order by满足与分析函数配合的开窗函数 over() 分析时要求的排序,即sql语句中的order by子句里的内容和开窗函数over() 中的order by子句里的内容一样,那么sql语句中的排序将先执行,分析函数在分析时就不必再排序;
    b) 两者不一致:如果sql语句中的order by不满足与分析函数配合的开窗函数over() 分析时要求的排序,即sql语句中的order by子句里的内容和开窗函数over() 中的order by子句里的内容不一样,那么sql语句中的排序将最后在分析函数分析结束后执行排序。

常用的分析函数:

1、row_number() over(partition by ... order by ...)  为每一条记录返回一个唯一的值。当碰到相同数据时,排名按照记录集中记录的顺序依次递增,现实情景为:个人在分组内的排名
2、rank() over(partition by ... order by ...)  得到每条记录在数据中的排名,排名不跳跃
3、dense_rank() over(partition by ... order by ...) 得到每条记录在数据中的排名,排名跳跃
4、count() over(partition by ... order by ...) 每个分组中,某个字段的统计
5、max() over(partition by ... order by ...)
6、min() over(partition by ... order by ...)
7、sum() over(partition by ... order by ...)

select ename,deptno,sal,sum(sal) over(partition by deptno order by ename) as A from emp

8、avg() over(partition by ... order by ...)
9、first_value() over(partition by ... order by ...) 得到第一个记录值
10、last_value() over(partition by ... order by ...) 得到最后一个记录值
11、lag() over(partition by ... order by ...) lag函数可以在一次查询中取出同一字段的前n行的数据

# lag(arg1,arg2,arg3)
# 第一个参数是列名,
# 第二个参数是偏移的offset,
# 第三个参数是超出记录窗口时的默认值。
select id,name,lag(name,1,0) over(order by id) from kkk;

12、lead() over(partition by ... order by ...) lead函数可以在一次查询中取出同一字段的后n行的值

4、去重

1、利用rowid的唯一性查询或删除重复数据

select ROWNUM,ROWID,d1.* from dept2 d1 where d1.rowid=(select min(d2.rowid) from dept2 d2 where d2.deptno=d1.deptno);

2、给定重复行序号并去重

SELECT FWZL
FROM (SELECT FWZL,
ROW_NUMBER() OVER(PARTITION BY FWZL ORDER BY ID DESC) RN
FROM T_FWXX) F
WHERE F.RN = 1

5、求占比、小计和总计

分析函数 RATIO_TO_REPORT 用来计算当前记录的指标 expr 占开窗函数 over 中包含记录的所有同一指标的百分比, 这里如果开窗函数的统计结果为 null 或者为 0,就是说占用比率的被除数为 0 或者为 null,则得到的结果也为 0。 开窗条件 query_partition_clause 决定被除数的值,如果用户忽略了这个条件,则计算查询结果中所有记录的汇总值。用户不能使用其他分析函数或者 ratio_to_report 作为分析函数 ratio_to_report 的参数 expr,也就是说这个函数。

 百分比

select deptno,ename,empno,round(RATIO_TO_REPORT(sal) OVER(PARTITION BY deptno)*100,1) 百分比 from emp

rollup() 与cube():排列组合分组

ROLLUP,是GROUP BY子句的一种扩展,可以为每个分组返回小计记录以及为所有分组返回总计记录。

CUBE,也是GROUP BY子句的一种扩展,可以返回每一个列组合的小计记录,同时在末尾加上总计记录。

group by rollup(a, b, c)

  1. 首先会对(a、b、c)进行group by,
  2. 然后再对(a、b)进行group by,
  3. 其后再对(a)进行group by,
  4. 最后对全表进行汇总操作。

group by cube(a, b, c):

  1. 则首先会对(a、b、c)进行group by,
  2. 然后依次是(a、b),(a、c),(a),(b、c),(b),(c),
  3. 最后对全表进行汇总操作。

求每个分组的总计

select deptno,sal,sum(sal) from emp group by rollup(deptno,sal)

求每一个列的组合的小计

select deptno,sum(sal) from emp group by cube(deptno,sal)

6、单条记录插入多表

原理:利用一个insert all 语法:insert all when .. then

INSERT ALL WHEN LOCALE = 1 THEN INTO EMPLOYEE1(ID, LOCALE, NAME, AGE, GENDER, CODE) VALUES (ID, LOCALE, NAME, AGE, GENDER, CODE)
WHEN LOCALE = 32 THEN INTO EMPLOYEE2(ID, LOCALE, NAME, AGE, GENDER, CODE) VALUES(ID, LOCALE, NAME, AGE, GENDER, CODE)
insert all into table values()
into table values()

7、Merge 的使用

解释:DML语句,适用于批量处理

   MERGE INTO table_name alias1
  USING (table|view|sub_query) alias2
  ON (join condition)
  WHEN MATCHED THEN
  UPDATE table_name
  SET col1 = col_val1,
  col2 = col2_val where 条件
  WHEN NOT MATCHED THEN
  INSERT (column_list) VALUES (column_values) where 条件;
MERGE INTO EMPLOYEE E

USING (SELECT * FROM EMPLOYEE1) E1
ON (E.NAME = E1.NAME)
WHEN MATCHED THEN
UPDATE SET E.CODE = E1.CODE, E.AGE = E1.AGE
WHEN NOT MATCHED THEN
INSERT (E.ID, E.LOCALE, E.NAME, E.AGE, E.GENDER, E.CODE) VALUES(E1.ID, E1.LOCALE, E1.NAME, E1.AGE, E1.GENDER, E1.CODE);
备注:对两张表的两个字段相匹配,如果匹配上了就做更新操作,否则就做插入操作。

8、KEEP的使用

keep是Oracle下的另一个分析函数,他的用法不同于通过over关键字指定的分析函数,可以用于这样一种场合下:取同一个分组下以某个字段排序后,对指定字段取最小或最大的那个值。

 MIN [ MAX ] (A) KEEP(DENSE_RANK FIRST [ LAST ] ORDER BY B)

这里引用别人说的明的解释一下:

DENSE_RANK

功能描述:根据ORDER BY子句中表达式的值,从查询返回的每一行,计算它们与其它行的相对位置。组内的数据按ORDER BY子句排序,然后给每一行赋一个号,从而形成一个序列,该序列从1开始,往后累加。每次ORDER BY表达式的值发生变化时,该序列也随之增加。有同样值的行得到同样的数字序号(认为null时相等的)。密集的序列返回的时没有间隔的数。

FIRST

功能描述:从DENSE_RANK返回的集合中取出排在最前面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。

LAST
功能描述:从DENSE_RANK返回的集合中取出排在最后面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。
所以默认排序下,FIRST可以理解是取小值,LAST取大值。而前面的MIN或者MAX则是在KEEP的结果集中取某一字段的最大值或最小值。

keep和普通分析函数的区别

  • 普通的分析函数只是列出分组后的记录,而对每一个组的记录进行统计分析。
  • keep对分组内的函数通过order by和max(),min()选取某个字段的值。可以理解成这里的keep就是sum() groud by deptno 前的sum()那样。

实例:取出各个部门薪资最高的员工编号

select deptno,empno,sal,max(empno) keep(dense_rank first order by sal desc) over(partition by deptno) from emp2

select deptno,max(empno) keep(dense_rank first order by sal desc) from emp2 group by deptno 

解释:按deptno分组,再对分组中的sal降序,取出第一个sal的员工号

9、SQL查询正则表达式的使用

ORACLE中的支持正则表达式的函数主要有下面四个:
1,REGEXP_LIKE :与LIKE的功能相似

select * from emp where regexp_like(empno,'7[0-9]{2}9');

2,REGEXP_INSTR :与INSTR的功能相似

REGEXP_INSTR 有 6 个参数

第一个是输入的字符串

第二个是正则表达式

第三个是标识从第几个字符开始正则表达式匹配。(默认为1)

第四个是标识第几个匹配组。(默认为1)

第五个是指定返回值的类型,如果该参数为0,则返回值为匹配位置的第一个字符,如果该值为非0则返回匹配值的最后一个位置。

第六个是是取值范围:

i:大小写不敏感;

c:大小写敏感;

n:点号 . 不匹配换行符号;

m:多行模式;

x:扩展模式,忽略正则表达式中的空白字符;

SELECT REGEXP_INSTR(a,'[0-9]+') AS A FROM test_reg_substr; 

3,REGEXP_SUBSTR

function REGEXP_SUBSTR(srcstr, pattern, position, occurrence, modifier)

srcstr:需要进行正则处理的字符串
pattern:进行匹配的正则表达式
position:起始位置,从第几个字符开始正则表达式匹配(默认为1)
occurrence:标识第几个匹配组,默认为1
modifie:模式('i'不区分大小写进行检索;'c'区分大小写进行检索。默认为'c'。)

查询使用正则分割后的第一个值,也就是34

SELECT REGEXP_SUBSTR('34,56,-23','[^,]+',1,1,'i') AS STR FROM DUAL

查询使用正则分割后的最后一个值,也就是23

SELECT REGEXP_SUBSTR('34,56,-23','[^,]+',1,3,'i') AS STR FROM DUAL

4,REGEXP_REPLACE :与REPLACE的功能相似

10、常见函数

TRUNC:截取函数
EXTRACT:用于从一个date或者interval类型中截取到特定的部分
NVL:
DECODE:行列转换
SOUNDEX:返回由四个字符组成的代码 (SOUNDEX) 以评估两个字符串的相似性
MONTHS_BETWEEN
ADD_MONTHS
NEXT_DAY
LAST_DAY
ROUND:函数用于把数值字段舍入为指定的小数位数
WITHIN GROUP:
select rank(1500) within group (order by sal desc) "rank of 1500" from emp;
解释:如果存在一条记录,这条记录的salary字段值为1500。那么将该条记录插入emp表中后,按照sal字段降序排列后,该条记录的序号为多少?

可以使用 within group 关键字的函数有 rank,dense_rank,PERCENT_RANK,PERCENTILE_CONT,PERCENTILE_DISC等  

11、分页函数

-- 普通写法
SELECT AA.FWZL, AA.FWTYBH
FROM (SELECT A.FWZL, A.FWTYBH, ROWNUM RN
FROM (SELECT F.FWZL, F.FWTYBH FROM FW F ORDER BY F.FWTYBH DESC) A
WHERE ROWNUM <= 120020) AA
WHERE AA.RN > 120000;
-- rowid写法
SELECT /*+ ROWID(FW) */ FW.FWZL, FW.FWTYBH
FROM FW FW,
(SELECT AA.RID, AA.RN
FROM (SELECT A.RID, ROWNUM RN
FROM (SELECT /*+ index(F IDX_FW_FWTYBH) */
ROWID RID
FROM FW F
ORDER BY F.FWTYBH DESC) A
WHERE ROWNUM <= 120020) AA
WHERE AA.RN > 120000) B
WHERE FW.ROWID = B.RID;

SQL优化一(SQL使用技巧)的更多相关文章

  1. SQL优化之SQL 进阶技巧(下)

    上文( SQL优化之SQL 进阶技巧(上) )我们简述了 SQL 的一些进阶技巧,一些朋友觉得不过瘾,我们继续来下篇,再送你 10 个技巧 一. 使用延迟查询优化 limit [offset], [r ...

  2. SQL优化之SQL 进阶技巧(上)

    由于工作需要,最近做了很多 BI 取数的工作,需要用到一些比较高级的 SQL 技巧,总结了一下工作中用到的一些比较骚的进阶技巧,特此记录一下,以方便自己查阅,主要目录如下: SQL 的书写规范 SQL ...

  3. [terry笔记]Oracle SQL 优化之sql tuning advisor (STA)

    前言:经常可以碰到优化sql的需求,开发人员直接扔过来一个SQL让DBA优化,然后怎么办? 当然,经验丰富的DBA可以从各种方向下手,有时通过建立正确索引即可获得很好的优化效果,但是那些复杂SQL错综 ...

  4. SQL优化(SQL TUNING)可大幅提升性能的实战技巧之一——让计划沿着索引跑

    我们进行SQL优化时,经常会碰到对大量数据集进行排序,然后从排序后的集合取前部分结果的需求,这种情况下,当我们按照常规思路去写SQL时,系统会先读取过滤获得所有集合,然后进行排序,再从排序结果取出极少 ...

  5. SQL优化- 数据库SQL优化——使用EXIST代替IN

    数据库SQL优化——使用EXIST代替IN 1,查询进行优化,应尽量避免全表扫描 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引 . 尝试下面的 ...

  6. Oracle自带工具sql优化集-SQL Tuning Advisor (使用心得体会)

    如何有效的诊断和监控高负载的SQL对于DBA来说并非是件容易的事情,对SQL语句手工调优需要很多的经验和技巧, 结合个人经验常见如下问题:          . 对SQL语句本身进行优化以便获得更优的 ...

  7. oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)

    1.   简介 Oracle Database11gR1引进了SQL PlanManagement(简称SPM),一套允许DBA捕获和保持任意SQL语句执行计划最优的新工具,这样,限制了刷新优化器统计 ...

  8. Oracle12c中SQL优化(SQL TUNING)新特性之SQL计划指令

    SQL计划指令是Oracle12c中自适应查询优化的功能之一.SQL计划指令就像“额外的提醒” ,用以提醒优化器你先前选择了的计划并不是最优的,典型的是因为错误的势评估.错误的势评估往往是由统计信息缺 ...

  9. 【SQL优化】SQL优化工具

    SQLAdvisor 是由美团点评公司北京DBA团队开发维护的 SQL 优化工具:输入SQL,输出索引优化建议. 它基于 MySQL 原生词法解析,再结合 SQL 中的 where 条件以及字段选择度 ...

  10. SQL优化工具 - SQL Server Profiler与数据库引擎优化顾问

    最近项目做到几千个学生分别去人脸识别记录(目前约630000行)中查询最后一次记录,可想而知性能这块是个麻烦.于是乎,GET到了SQL Server Profiler和数据库引擎优化顾问这俩工SHEN ...

随机推荐

  1. html快速编写

    1. 嵌套操作---------- 子操作: > div>ul>li <div> <ul> <li></li> </ul> ...

  2. CSS3中的一些属性

    1. 可匹配部分字符串 2. box-sizing属性 3. CSS3多栏布局 1.可匹配部分字符串 /*^运算符,匹配字符串首部*/ a[href^='http://website'] /*$运算符 ...

  3. Javascript高级编程学习笔记(67)—— 事件(11)HTML5事件

    DOM规范没有涵盖所有浏览器支持的所有事件 而许多浏览器出于满足用户需求,或解决特殊问题的目的,实现了一些自定义事件 HTML5列出了浏览器应该支持的所有事件,这里只讨论得到浏览器完善支持的事件(并非 ...

  4. 吴恩达机器学习笔记40-用调和平均数F来进行查准率和查全率之间的权衡(Trading Off Precision and Recall by F sore)

    在很多应用中,我们希望能够保证查准率和查全率的相对平衡. 我们可以将不同阀值情况下,查全率与查准率的关系绘制成图表,曲线的形状根据数据的不同而不同: 我们希望有一个帮助我们选择这个阀值的方法.一种方法 ...

  5. HOG算法资源备忘

    最近再研究这个算法,找了不少资料来研究,发现这方面的资料好的并不多,今天就把找到的经典的资料做一个汇总,方便后续查阅吧. 一 基本概念和推导: 1 解释最清楚的:中文网站:https://blog.c ...

  6. npm ERR! Refusing to install package with name "webpack" under a package -----

    当我们在安装以一些依赖的时候会提示以下报错--------- 问题出在: 这个name 不能使用所需要安装包的名字! 解决方案----- 修改下就行 -- -我将wenpack 改成webpack1 ...

  7. Python中的算数运算

    算数运算符 计算机,顾名思义就是负责进行 数学计算 并且 存储计算结果 的电子设备 目标 算术运算符的基本使用 01. 算数运算符 算数运算符是 运算符的一种 是完成基本的算术运算使用的符号,用来处理 ...

  8. C/C++结构体成员偏移量获取

    分析代码节选自muduo. 以下代码通过offsetof获取sin_family在sockaddr_in6中的字段偏移量. static_assert(offsetof(sockaddr_in6, s ...

  9. Spring Boot 返回 XML 数据,一分钟搞定!

    Spring Boot 返回 XML 数据,前提必须已经搭建了 Spring Boot 项目,所以这一块代码就不贴了,可以点击查看之前分享的 Spring Boot 返回 JSON 数据,一分钟搞定! ...

  10. 1.numpy的用法

    numpy创建ndarray对象的三种方法 1.1.list转化 In [8]: import numpy as np In [9]: a = [1,2,3,4] In [10]: x1 = np.a ...