SQL Fundamentals || Oracle SQL语言

子查询(基础)

1、认识子查询

2、WHERE子句中使用子查询

3、在HAVING子句中使用子查询

4、在FROM子句中使用子查询

5、在SELECT子句中使用子查询

6、WITH子句

子查询(进阶)

7、分析函数

8、行列转换

9、设置数据层次

七、分析函数

  • 分析函数语法;
  • 分窗操作的;
  • 使用分析函数可以进行更为复杂的查询报表显示。
  • 在分析函数中可以使用若干统计函数.

传统SQL的问题

虽然利用SQL之中提供的各种查询命令可以完成大部分的查询要求,但是还有许多功能是无法实现的,例如:

  • 计算运行总量:逐一累加当前行与其之前行的每行记录数据;
  • 查找当前行数据占总数据的百分比;
  • 分区显示:按照不同的部门或职位进行排列、统计;
  • 计算流动数据行的平均值等。

分析函数的基本语法

基本语法:

函数名称([参数 , ....]) OVER (

PARTITION BY 子句 字段 , …

[ORDER BY 子句 字段 , … [ASC | DESC] [NULLS FIRST | NULLS LAST]

[WINDOWING 子句]) ;

语法组成:

函数名称

类似于统计函数(COUNT()、SUM()等),但是在此时有了更多的函数支持;

OVER子句

为分析函数指明一个查询结果集,此语句在SELECT子句之中使用;

PARTITION BY子句

将一个简单的结果集分为N组(或称为分区),而后按照不同的组对数据进行统计;

ORDER BY 子句

明确指明数据在每个组内的排列顺序,分析函数的结果与排列顺序有关;

NULLS FIRST | NULLS LAST:表示返回数据行中包含NULL值是出现在排序序列前还是尾;

NULLS FIRST

NULLS FIRST表示在进行排序前,出现null值的数据行排列在最前面,

NULLS LAST

NULLS LAST则表示出现的null值数据行排列在最后面。

使用NULLS LAST

SELECT deptno , ename, sal , comm ,

RANK() OVER (ORDER BY comm DESC NULLS LAST) rk ,

SUM(sal) OVER (ORDER BY comm DESC NULLS LAST) SUM

FROM emp ;

WINDOWING 子句(代名词)

给出在定义变化的固定的数据窗口方法,分析函数将对此数据进行操作。

组合顺序:

在分析函数之中存在有三种子句:PARTITION BY、ORDER BY、WINDOWING,而这三种子句的组合顺序有如下几种:

组合1

函数名称([参数 ,…]) OVER(PARTITION BY 子句 , ORDER BY 子句 , WINDOWING子句);

组合2

函数名称([参数 ,…]) OVER(PARTITION BY 子句 , ORDER BY 子句);

组合3

函数名称([参数 ,…]) OVER(PARTITION BY 子句);

组合4

函数名称([参数 ,…]) OVER(ORDER BY 子句 , WINDOWING子句);

组合5

函数名称([参数 ,…]) OVER(ORDER BY 子句);

组合6

函数名称([参数 ,…]) OVER();

基本查询语句中是不能出现字段和统计函数同时出现的.(如下语法是错误的)

SELECT deptno , ename, sal ,

SUM(sal)

FROM emp ;

1、PARTITION子句和ORDER BY子句的使用

使用PARTITION子句

按照部门范畴进行统计;每行数据之后都会有统计的结果出现.

同一部门的雇员的SUM(sal)的值相同,并且值等于同一部门雇员sal的相加.

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno) sum

FROM emp ;

不使用PARTITION进行分区,直接利用OVER子句操作——如果没有分区就会把所有的数据当成一个区,然后进行统计.

SELECT deptno , ename, sal ,

SUM(sal) OVER () sum

FROM emp ;

通过PARTITION设置多个分区字段——分析部门编号和职位进行分区

这里的范畴:先按照部门分区,再按照职位分区,返回的结果是:每个部门中职位的总工资

SELECT deptno , ename, sal , job ,

SUM(sal) OVER (PARTITION BY deptno , job) sum

FROM emp ;

观察ORDER BY子句

按照部门编号分区,按照工资降序排列(两个数据相同并列为1,后面一个数据为3)

SELECT deptno , ename, sal ,

RANK() OVER (PARTITION BY deptno ORDER BY sal DESC) rk

FROM emp ;

设置多个排序字段(sal和hiredate)

SELECT deptno , ename, sal , hiredate ,

RANK() OVER (PARTITION BY deptno ORDER BY sal , hiredate DESC) rk

FROM emp ;

直接利用ORDER BY排序所有数据——如果不写分区操作,就表示所有的数据进行排序

先将所有数据变为一组,而后按照姓名进行排序;

排序后,第一个数据的sum(sal)值为其sal本身,第二个数据的sum(sal)值为第一个数据和第二个数据的总和,以此类推.

SELECT deptno , ename, sal , hiredate ,

SUM(sal) OVER (ORDER BY ename DESC) SUM

FROM emp ;

2、WINDOWING子句

分窗子句主要是用于定义一个变化或固定的数据窗口方法,主要用于定义分析函数在操作行的集合,分窗子句有两种实现方式:

值域窗(RANGE WINDOW),逻辑偏移

当前分区之中当前行的前N行到当前行的记录集;

行窗(ROWS WINDOW),物理偏移

以排序的结果顺序计算偏移当前行的起始行记录集。

而如果要想指定RANGE(值域窗)或ROWS(行窗)的偏移量,则可以采用如下的几种排序列:

1

RANGE | ROWS 数字 PRECEDING;

2

RANGE | ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW;

3

RANGE | ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING;

以上的几种排列之中包含的概念如下:

PRECEDING

主要是设置一个偏移量,这个偏移量可以是用户设置的数字,或者是其他标记;

BETWEEN … AND

设置一个偏移量的操作范围;

UNBOUNDED PRECEDING

不限制偏移量大小;

CURRENT ROW

表示当前行;

FOLLOWING

如果不写此语句表示使用上N行与当前行指定数据比较,如果编写此语句,表示当前行与下N行数据比较;

例子:

RANGE子句:RANGE子句设置的是一个逻辑的偏移量

在sal上设置偏移量(PRECEDING)

按照向上N行的记录偏移

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal RANGE 300 PRECEDING) sum

FROM emp ;

设置偏移量为300,采用下匹配方式处理

向下匹配方式,显示结果向下N行的记录偏移

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal RANGE BETWEEN 0 PRECEDING AND 300 FOLLOWING) sum

FROM emp ;

匹配当前行数据

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal RANGE BETWEEN 0 PRECEDING AND CURRENT ROW) sum

FROM emp ;

使用UNBOUNDED不设置边界

现在的结果是在一个区域内进行逐行的操作.

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal RANGE BETWEENUNBOUNDED PRECEDING AND CURRENT ROW) sum

FROM emp ;

ROWS子句:ROWS子句设置的是一个物理的偏移量

设置2行物理偏移

按照部门编号分组,而后采用当前行和前2行数据进行计算.

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal ROWS 2 PRECEDING) sum

FROM emp ;

设置查询行范围

此时和按照部门分区进行求和道理相同.

SELECT deptno , ename, sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) sum

FROM emp ;

分析函数:

1、数据统计函数

2、等级函数

3、报表函数

1、数据统计函数

函数名称

描述

SUM([DISTINCT | ALL] 表达式)

计算分区(分组)中的数据累加和

MIN([DISTINCT | ALL] 表达式)

查找分区(分组)中的最小值

MAX([DISTINCT | ALL] 表达式)

查找分区(分组)中的最大值

AVG([DISTINCT | ALL] 表达式)

计算分区(分组)中的数据平均值

COUNT(* | [DISTINCT | ALL] 表达式)

计算分区(分组)中的数据量

查询雇员编号是7369的雇员姓名、职位、基本工资、部门编号、部门的人数、平均工资、最高工资、最低工资、总工资

SELECT *

FROM (

SELECT empno,ename,job,sal,deptno ,

COUNT(empno) OVER (PARTITION BY deptno) count ,

ROUND(AVG(sal) OVER (PARTITION BY deptno)) avg ,

SUM(sal) OVER (PARTITION BY deptno) sum ,

MAX(sal) OVER (PARTITION BY deptno) max ,

MIN(sal) OVER (PARTITION BY deptno) min

FROM emp ) temp

WHERE temp.empno=7369 ;

法二:

WITH t AS(

SELECT empno,ename,job,sal,deptno ,

COUNT(empno) OVER (PARTITION BY deptno) count ,

ROUND(AVG(sal) OVER (PARTITION BY deptno)) avg ,

SUM(sal) OVER (PARTITION BY deptno) sum ,

MAX(sal) OVER (PARTITION BY deptno) max ,

MIN(sal) OVER (PARTITION BY deptno) min

FROM emp )

SELECT * FROM t

WHERE t.empno=7369 ;

查询每个雇员的编号、姓名、基本工资、所在部门的名称、部门位置以及此部门的平均工资、最高和最低工资

确定所需要的数据表:dept表:部门信息,名称,位置

emp表:雇员姓名,统计信息

确定已知的关联字段:

雇员和部门:emp.deptno=dept.deptno

步骤一:进行多表关联

步骤二:加入统计信息(部门的平均工资、最高和最低工资:使用分析函数,进行分窗)

SELECT e.empno , e.ename , e.sal , d.dname , d.loc ,

ROUND(AVG(sal) OVER (PARTITION BY e.deptno ORDER BY sal

RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) avg_salary ,

MAX(sal) OVER (PARTITION BY e.deptno ORDER BY sal

RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) max_salary ,

MIN(sal) OVER (PARTITION BY e.deptno ORDER BY sal

RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) min_salary

FROM emp e,dept d

WHERE e.deptno=d.deptno ;

2、等级函数

为数据进行排序编号

函数名称

描述

RANK()

根据ORDER BY子句的排序字段,从分区(分组)查询每一行数据,按照排序生成序号,会出现相同序号,跳号

DENSE_RANK()

根据ORDER BY子句的排序字段,从分区(分组)查询每一行数据,按照排序生成序号,不跳号

FIRST

取出DENSE_RANK返回集合中第一行数据

LAST

取出DENSE_RANK返回集合中最后一行数据

FIRST_VALUE(列)

返回分区(分组)中的第一个值

LAST_VALUE(列)

返回分区(分组)中的最后一个值

LAG(列名称 [, 行数字] [, 默认值])

访问分区(分组)中指定前N行的记录,如果没有则返回默认值

LEAD(列名称 [, 行数字] [, 默认值])

访问分区(分组)中指定后N行的记录,如果没有则返回默认值

ROW_NUMBER()

返回每组中的行号

RANK()和DENSE_RANK()函数

SELECT deptno,ename,sal,

RANK() OVER (PARTITION BY deptno ORDER BY sal) rank_result ,

DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal) dense_rank_result

FROM emp ;

ROW_NUMBER()函数

针对所有数据,ROW_NUMBER()自动生成了行号,但是在每个分区里面,也按照部门生成行号

SELECT deptno,ename,sal,

ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY sal) row_result_deptno ,

ROW_NUMBER() OVER (ORDER BY sal) row_result_all

FROM emp ;

KEEP语句

    • 保留满足条件的数据,在使用DENSE_RANK()函数确定的集合后,通过FIRST或LAST取得集合中的数据.

分组函数 ()

KEEP

(DENSE_RANK FIRST | LAST ORDER BY 表达式 [ASC | DESC] [NULLS [FIRST | LAST]] , ...)

[OVER () 分区查询] ;

查询每个部门的最高及最低工资

SELECT deptno,

MAX(sal) KEEP (DENSE_RANK FIRST ORDER BY sal DESC) max_salary ,

MIN(sal) KEEP (DENSE_RANK LAST ORDER BY sal DESC) min_salary

FROM emp

GROUP BY deptno ;

FIRST_VALUE()与LAST_VALUE()函数

SELECT deptno , empno , ename , sal ,

FIRST_VALUE(sal) OVER (PARTITION BY deptno ORDER BY sal

RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) first_result ,

LAST_VALUE(sal) OVER (PARTITION BY deptno ORDER BY sal

RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) last_result

FROM emp

WHERE deptno=10 ;

LAG()与LEAD()函数

相邻记录的比较

SELECT deptno , empno , ename , sal ,

LAG(sal,2,0) OVER (PARTITION BY deptno ORDER BY sal ) lag_result ,

LEAD(sal,2,0) OVER (PARTITION BY deptno ORDER BY sal ) lead_result

FROM emp

WHERE deptno=20 ;

3、报表函数

函数名称

描述

CUME_DIST()

计算一行在分区(分组)中的相对位置,如果分区有5条记录,记录会按照1、0.8、0.6、0.4、0.2的方式进行划分

NTILE(数字)

将一个分区(分组)分为“表达式”的散列表示

针对数据分区中的有序结果集进行划分

RATIO_TO_REPORT(表达式)

该函数计算expression/(sum(expression))的值,它给出相对于总数的百分比

验证CUME_DIST()函数

SELECT deptno,ename,sal ,

CUME_DIST() OVER (PARTITION BY deptno ORDER BY sal) cume

FROM emp

WHERE deptno IN (10,20) ;

使用NTILE()函数

SELECT deptno , sal ,

SUM(sal) OVER (PARTITION BY deptno ORDER BY sal) sum_result ,

NTILE(3) OVER (PARTITION BY deptno ORDER BY sal) ntile_result_a ,

NTILE(6) OVER (PARTITION BY deptno ORDER BY sal) ntile_result_b

FROM emp ;

RATIO_TO_REPORT

计算各部门工资所占的总工资比率

SELECT deptno ,SUM(sal) ,

ROUND(RATIO_TO_REPORT(SUM(sal)) OVER () ,5) rate ,

ROUND(RATIO_TO_REPORT(SUM(sal)) OVER () ,5) * 100 || '%' precent

FROM emp

GROUP BY deptno;

SQL Fundamentals: 子查询 || 分析函数(PARTITION BY,ORDER BY, WINDOWING)的更多相关文章

  1. SQL Fundamentals: 子查询 || 行列转换(PIVOT,UNPIVOT,DECODE),设置数据层次(LEVEL...CONNECT BY)

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  2. SQL Fundamentals: 子查询 || WHERE,HAVING,FROM,SELECT子句中使用子查询,WITH子句

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  3. SQL的子查询操作

    对于表中的每一个记录,我们有时候需要提取特殊的或者你需要的记录,要提前做一个表的筛选,之后再对你选出的记录做一个修改,此时你必须使用SQL的子查询操作.如:修改id=5的记录的strContent字段 ...

  4. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

  5. SQL关联子查询

    SQL关联子查询执行顺序: 1.先取到主查询中的相关数据,一次取一行主查询的数据 2.然后传入子查询,进行子查询 3.最后做主查询where筛选,注意子查询的where条件同样需要加在主查询后 参考: ...

  6. SQL SERVER 子查询使用Order By;按In排序

    [子查询]使用order by percent * from table order by id) a 这时发现结果没有按id排序,需要将100 percent 改成 99.999 percent 或 ...

  7. Linq To Sql 语法 子查询 & In & Join

    子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 =from cin ctx.Customers                    where                  ...

  8. SQL随着子查询结果更新多个字段

    笔者:iamlasong 要求:表格内容需要改变,在临时表中内容的变化,使用SQL官方声明更新表若干领域. 假设更新一个字段,直接用字段名=子查询就能够了,多个字段更新,将字段在括号里并列写出就可以, ...

  9. SQL 数据库 子查询及示例

    子查询,又叫做嵌套查询. 将一个查询语句做为一个结果集供其他SQL语句使用,就像使用普通的表一样,被当作结果集的查询语句被称为子查询. 子查询有两种类型: 一种是只返回一个单值的子查询,这时它可以用在 ...

随机推荐

  1. PHP类中self和$this的区别

    1.self代表类,$this代表对象2.能用$this的地方一定使用self,能用self的地方不一定能用$this静态的方法中不能使用$this,静态方法给类访问的. 今天在使用静态方法的时候,使 ...

  2. 【MySQL】MySQL查询数据库各表的行数

    #倒序查询数据库[各表记录数] use information_schema; select table_name,table_rows from tables where TABLE_SCHEMA ...

  3. 用反向代理nginx proxy_pass配置解决ie8 ajax请求被拦截问题 ie8用nginx代理实现跨域请求访问 nginx405正向代理request_uri

    最近调PC版网站ie8的兼容性,发现所有ajax请求还没到后端服务器就直接ajax error了 ie8发不出ajax请求,断点调试发现ajax全进入了error,提示“No transport” 我 ...

  4. DES算法原理完整版

    1.所需参数 key:8个字节共64位的工作密钥 data:8个字节共64位的需要被加密或被解密的数据 mode:DES工作方式,加密或者解密 2.初始置换 DES算法使用64位的密钥key将64位的 ...

  5. MySQL查询库和表占用的硬盘空间大小

    在mysql中有一个默认的数据表information_schema,information_schema这张数据表保存了MySQL服务器所有数据库的信息.如数据库名,数据库的表,表栏的数据类型与访问 ...

  6. 转载:Quartz.NET 入门

    分享自:http://www.cnblogs.com/jys509/p/4628926.html 概述 Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮 ...

  7. vim几种常用的插入模式

    我们来看一下cw这个命令,它是从光标处替换到后一个单词的结尾.比如说我的光标如图: 我的namespace写错了,后面的都对,就可以用cw命令,

  8. [C++]Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)

    https://www.cnblogs.com/senior-engineer/p/5598133.html https://www.cnblogs.com/findumars/p/5607683.h ...

  9. [Linux 性能调优] 网卡中断与CPU的绑定问题

    在Linux的网络调优方面,如果你发现网络流量上不去,那么有一个方面需要去查一下:网卡处理网络请求的中断是否被绑定到单个CPU(或者说跟处理其它中断的是同一个CPU). 先说一下背景 网卡与操作系统的 ...

  10. neo1973 audio subsystem

    fhttp://wiki.openmoko.org/wiki/Neo_1973_audio_subsystem using Bluetooth headset with GSM NOTE none o ...