您的位置:首页 > 数据库 > Oracle

Oracle分析函数

2016-04-09 17:27 337 查看
01.Oracle分析函数

--运行总计:比如逐行显示在某些部门中的累计汇总工资,每行包含前面各行工资之和,

--查找一组内的百分数:比如显示在某些部门中付给个人的总工资百分数,将他们的工资与该部门的工资总和相除

--前n个查询:查询指定条件的前N个记录

--移动平均值计算:将当前行的值与前N行的值 加一起求平均值

--执行等级查询:比如显示一个部门内某个员工工资的相关等级

select ename,

deptno,

sal,

sum(sal) over(order by deptno, ename) 运行总计,

sum(sal) over(partition by deptno order by ename) 分部门运行统计,

row_number() over(partition by deptno order by ename) 序列

from emp

where deptno in (10, 20)

order by deptno, ename;

SQL> select ename,

2 deptno,

3 sal,

4 sum(sal) over(order by deptno, ename) 运行总计,

5 sum(sal) over(partition by deptno order by ename) 分部门运行统计,

6 row_number() over(partition by deptno order by ename) 序列

7 from emp

8 where deptno in (10, 20)

9 order by deptno, ename;

ENAME DEPTNO SAL 运行总计 分部门运行统计 序列

---------- ---------- ---------- ---------- -------------- ----------

CLARK 10 2450 2450 2450 1

KING 10 5000 7450 7450 2

MILLER 10 1300 8750 8750 3

ADAMS 20 1100 9850 1100 1

FORD 20 3000 12850 4100 2

JONES 20 2975 15825 7075 3

SCOTT 20 3000 18825 10075 4

SMITH 20 800 19625 10875 5

已选择8行。

02.Oracle分析函数_不指定排序规则

指定排序规则

SQL> select ename, deptno, sal, sum(sal) over(order by ename) 运行总计

2 from emp

3 where deptno in (10, 20);

ENAME DEPTNO SAL 运行总计

---------- ---------- ---------- ----------

ADAMS 20 1100 1100

CLARK 10 2450 3550

FORD 20 3000 6550

JONES 20 2975 9525

KING 10 5000 14525

MILLER 10 1300 15825

SCOTT 20 3000 18825

SMITH 20 800 19625

已选择8行。

--注意 sum要进行运行总计计算,如果不指定排序规则,在运行总计栏只能看到相同的结果,如下

SQL> select ename, deptno, sal, sum(sal) over() 运行总计

2 from emp

3 where deptno in (10, 20);

ENAME DEPTNO SAL 运行总计

---------- ---------- ---------- ----------

SMITH 20 800 19625

JONES 20 2975 19625

CLARK 10 2450 19625

SCOTT 20 3000 19625

KING 10 5000 19625

ADAMS 20 1100 19625

FORD 20 3000 19625

MILLER 10 1300 19625

已选择8行。

03.统计部门中各部门中不同职位的薪资总计,同时显示不同职位的薪资的运行总计

SQL> select o.deptno,

2 o.job,

3 sum(o.sal) 部门职称汇总,

4 sum(sum(o.sal)) over(partition by o.deptno order by o.job) 部门薪资

运行汇总

5 from emp o

6 where deptno in (10, 20, 30)

7 and job is not null

8 group by o.deptno, o.job

9 order by o.deptno;

DEPTNO JOB 部门职称汇总 部门薪资运行汇总

---------- --------- ------------ ----------------

10 CLERK 1300 1300

10 MANAGER 2450 3750

10 PRESIDENT 5000 8750

20 ANALYST 6000 6000

20 CLERK 1900 7900

20 MANAGER 2975 10875

30 CLERK 950 950

30 MANAGER 2850 3800

30 SALESMAN 5600 9400

已选择9行。

04_等级函数.

SQL> select o.deptno,

2 --o.job,

3 sum(o.sal) 部门职称汇总,

4 rank() over(order by sum(o.sal) desc) 薪资等级,

5 dense_rank() over(order by sum(o.sal) desc) dense_rank排名,

6 row_number() over(partition by o.deptno order by sum(o.sal) desc) 分

组行号,

7 sum(sum(o.sal)) over(partition by o.deptno order by o.job) 部门薪资

运行总计

8 from emp o

9 where o.deptno in (10, 20, 30)

10 and job is not null

11 group by o.deptno, o.job;

DEPTNO 部门职称汇总 薪资等级 DENSE_RANK排名 分组行号 部门薪资运行总计

---------- ------------ ---------- -------------- ---------- ----------------

20 6000 1 1 1 6000

30 5600 2 2 1 9400

10 5000 3 3 1 8750

20 2975 4 4 2 10875

30 2850 5 5 2 3800

10 2450 6 6 2 3750

20 1900 7 7 3 7900

10 1300 8 8 3 1300

30 950 9 9 3 950

已选择9行。

SQL>

05.分区子句

--使用row_number进行行号统计时使用分区

--注意 row_number 函数总是从1开始计数

SQL> select deptno,

2 empno,

3 ename,

4 row_number() over(partition by deptno order by empno) 分组

5 from emp

6 where deptno in (10, 20, 30);

DEPTNO EMPNO ENAME 分组行号

---------- ---------- ---------- ----------

10 7782 CLARK 1

10 7839 KING 2

10 7934 MILLER 3

20 7369 SMITH 1

20 7566 JONES 2

20 7788 SCOTT 3

20 7876 ADAMS 4

20 7902 FORD 5

30 7499 ALLEN 1

30 7521 WARD 2

30 7654 MARTIN 3

DEPTNO EMPNO ENAME 分组行号

---------- ---------- ---------- ----------

30 7698 BLAKE 4

30 7844 TURNER 5

30 7900 JAMES 6

已选择14行。

06.排序子句

--order by 子句用于指定分组中数据的排序方式,排序方式会明显地影响任何分析函数的结果,举例来说,在进行AVG

--运算时,如果不指定排序,将会看到所有的结果都相同

--排序子句SQL> select ename, sal, avg(sal) over() from emp where rownum <= 3;

ENAME SAL AVG(SAL)OVER()

---------- ---------- --------------

SMITH 800 1216.66667

ALLEN 1600 1216.66667

WARD 1250 1216.66667

--如果指定按ename排序,其结果又大不一样

SQL> select ename, sal, avg(sal) over( order by ename) from emp where rownum <=

3;

ENAME SAL AVG(SAL)OVER(ORDERBYENAME)

---------- ---------- --------------------------

ALLEN 1600 1600

SMITH 800 1200

WARD 1250 1216.66667

07.开窗子句

--开窗子句

--从当前记录开始直至某个部分的最后一条记录结束记录

--从统计时可以统计分组以外的记录

--在当前行的前几行或后几行进行滚动计算

SQL> select deptno,

2 sum(sal) 部门薪资小计,

3 sum(sum(sal)) over(order by deptno rows between unbounded preceding

and unbounded following) 部门总计

4 from emp

5 group by deptno;

DEPTNO 部门薪资小计 部门总计

---------- ------------ ----------

10 8750 29025

20 10875 29025

30 9400 29025

08.分析函数列表 count函数

SQL> select empno,

2 ename,

3 count(*) over(partition by deptno order by empno) 条数统计

4 from emp;

EMPNO ENAME 条数统计

---------- ---------- ----------

7782 CLARK 1

7839 KING 2

7934 MILLER 3

7369 SMITH 1

7566 JONES 2

7788 SCOTT 3

7876 ADAMS 4

7902 FORD 5

7499 ALLEN 1

7521 WARD 2

7654 MARTIN 3

EMPNO ENAME 条数统计

---------- ---------- ----------

7698 BLAKE 4

7844 TURNER 5

7900 JAMES 6

已选择14行。

--通过range between来判断sal值是否在50-150之间

SQL> select empno,

2 ename,

3 sal,

4 count(*) over(order by sal range between 50 preceding and 150 follow

ing) 薪水差异个数

5 from emp;

EMPNO ENAME SAL 薪水差异个数

---------- ---------- ---------- ------------

7369 SMITH 800 2

7900 JAMES 950 2

7876 ADAMS 1100 3

7521 WARD 1250 3

7654 MARTIN 1250 3

7934 MILLER 1300 3

7844 TURNER 1500 2

7499 ALLEN 1600 1

7782 CLARK 2450 1

7698 BLAKE 2850 4

7566 JONES 2975 3

EMPNO ENAME SAL 薪水差异个数

---------- ---------- ---------- ------------

7788 SCOTT 3000 3

7902 FORD 3000 3

7839 KING 5000 1

已选择14行。

--09.分析函数列表 AVG

SQL> select deptno,

2 empno,

3 ename,

4 sal,

5 avg(sal) over(partition by deptno order by deptno) avg_sal

6 from emp;

DEPTNO EMPNO ENAME SAL AVG_SAL

---------- ---------- ---------- ---------- ----------

10 7782 CLARK 2450 2916.66667

10 7839 KING 5000 2916.66667

10 7934 MILLER 1300 2916.66667

20 7566 JONES 2975 2175

20 7902 FORD 3000 2175

20 7876 ADAMS 1100 2175

20 7369 SMITH 800 2175

20 7788 SCOTT 3000 2175

30 7521 WARD 1250 1566.66667

30 7844 TURNER 1500 1566.66667

30 7499 ALLEN 1600 1566.66667

DEPTNO EMPNO ENAME SAL AVG_SAL

---------- ---------- ---------- ---------- ----------

30 7900 JAMES 950 1566.66667

30 7698 BLAKE 2850 1566.66667

30 7654 MARTIN 1250 1566.66667

已选择14行。

10_分析函数列表min_max函数

SQL> select deptno,

2 empno,

3 ename,

4 hiredate,

5 sal,

6 min(sal) over(partition by deptno order by hiredate range unbounded

preceding) 最低薪水,

7 max(sal) over(partition by deptno order by hiredate range unbounded

preceding) 最高薪水

8 from emp;

DEPTNO EMPNO ENAME HIREDATE SAL 最低薪水 最高薪水

---------- ---------- ---------- -------------- ---------- ---------- ----------

10 7782 CLARK 09-6月 -81 2450 2450 2450

10 7839 KING 17-11月-81 5000 2450 5000

10 7934 MILLER 23-1月 -82 1300 1300 5000

20 7369 SMITH 17-12月-80 800 800 800

20 7566 JONES 02-4月 -81 2975 800 2975

20 7902 FORD 03-12月-81 3000 800 3000

20 7788 SCOTT 19-4月 -87 3000 800 3000

20 7876 ADAMS 23-5月 -87 1100 800 3000

30 7499 ALLEN 20-2月 -81 1600 1600 1600

30 7521 WARD 22-2月 -81 1250 1250 1600

30 7698 BLAKE 01-5月 -81 2850 1250 2850

DEPTNO EMPNO ENAME HIREDATE SAL 最低薪水 最高薪水

---------- ---------- ---------- -------------- ---------- ---------- ----------

30 7844 TURNER 08-9月 -81 1500 1250 2850

30 7654 MARTIN 28-9月 -81 1250 1250 2850

30 7900 JAMES 03-12月-81 950 950 2850

已选择14行。

11.--分析函数列表rank,dense_rank和row_number函数

SQL> select deptno,

2 ename,

3 sal,

4 --mgr,

5 rank() over(order by deptno) rank结果, dense_rank() over(order by d

eptno) dense_rank结果,

6 row_number() over(order by deptno) row_number结果

7 from emp

8 where deptno in (10, 20, 30);

DEPTNO ENAME SAL RANK结果 DENSE_RANK结果 ROW_NUMBER结果

---------- ---------- ---------- ---------- -------------- --------------

10 CLARK 2450 1 1 1

10 KING 5000 1 1 2

10 MILLER 1300 1 1 3

20 JONES 2975 4 2 4

20 FORD 3000 4 2 5

20 ADAMS 1100 4 2 6

20 SMITH 800 4 2 7

20 SCOTT 3000 4 2 8

30 WARD 1250 9 3 9

30 TURNER 1500 9 3 10

30 ALLEN 1600 9 3 11

DEPTNO ENAME SAL RANK结果 DENSE_RANK结果 ROW_NUMBER结果

---------- ---------- ---------- ---------- -------------- --------------

30 JAMES 950 9 3 12

30 BLAKE 2850 9 3 13

30 MARTIN 1250 9 3 14

已选择14行。

12_分析函数列表first和last函数

SQL> select deptno,

2 min(sal) keep(dense_rank first order by comm) 最低提成薪水,

3 max(sal) keep(dense_rank last order by comm) 最高提成薪水

4 from emp

5 group by deptno;

DEPTNO 最低提成薪水 最高提成薪水

---------- ------------ ------------

10 1300 5000

20 800 3000

30 1500 2850

--13.first_value和last_value函数

SQL> select deptno,

2 empno,

3 sal,

4 first_value(sal) over(partition by deptno order by empno) "第一个值

,

5 last_value(sal) over(partition by deptno order by empno) "最后一个值

"

6 from emp;

DEPTNO EMPNO SAL 第一个值 最后一个值

---------- ---------- ---------- ---------- ----------

10 7782 2450 2450 2450

10 7839 5000 2450 5000

10 7934 1300 2450 1300

20 7369 800 800 800

20 7566 2975 800 2975

20 7788 3000 800 3000

20 7876 1100 800 1100

20 7902 3000 800 3000

30 7499 1600 1600 1600

30 7521 1250 1600 1250

30 7654 1250 1600 1250

DEPTNO EMPNO SAL 第一个值 最后一个值

---------- ---------- ---------- ---------- ----------

30 7698 2850 1600 2850

30 7844 1500 1600 1500

30 7900 950 1600 950

已选择14行。

14.--lag和lead函数

--lag的功能是返回指定列col前n1行的值(如果前n1行已经超出比照范围,则返回n2,如果不指定n2则默认返回null),

--如果不指定n1,其默认值为1,lead函数与此相反,返回指定列col1后面的n1行的

--使用lag和lead函数查找当前雇员的前一个雇员的薪水后和后一个雇员薪水

SQL> select ename,

2 hiredate,

3 sal,

4 deptno,

5 lag(sal, 1, 0) over(order by hiredate) as "前一个雇员薪水",

6 lead(sal, 1, 0) over(order by hiredate) as "后一个雇员薪水"

7 from emp

8 where deptno = 30;

ENAME HIREDATE SAL DEPTNO 前一个雇员薪水 后一个雇员薪水

---------- -------------- ---------- ---------- -------------- --------------

ALLEN 20-2月 -81 1600 30 0 1250

WARD 22-2月 -81 1250 30 1600 2850

BLAKE 01-5月 -81 2850 30 1250 1500

TURNER 08-9月 -81 1500 30 2850 1250

MARTIN 28-9月 -81 1250 30 1500 950

JAMES 03-12月-81 950 30 1250 0

已选择6行。

--15.分析函数使用示例 记录排名

SQL> select deptno,

2 -- empno,

3 ename,

4 sum(sal) dept_sales,

5 rank() over(partition by deptno order by sum(sal) desc nulls last)

薪资排名_跳号,

6 dense_rank() over(partition by deptno order by sum(sal) desc nulls l

ast) 薪资排名_同级同号,

7 row_number() over(partition by deptno order by sum(sal) desc nulls l

ast) 薪资排名_不跳号

8 from emp

9 group by deptno, empno, ename;

DEPTNO ENAME DEPT_SALES 薪资排名_跳号 薪资排名_同级同号 薪资排名_不跳号

---------- ---------- ---------- ------------- ----------------- ---------------

10 KING 5000 1 1 1

10 CLARK 2450 2 2 2

10 MILLER 1300 3 3 3

20 FORD 3000 1 1 1

20 SCOTT 3000 1 1 2

20 JONES 2975 3 2 3

20 ADAMS 1100 4 3 4

20 SMITH 800 5 4 5

30 BLAKE 2850 1 1 1

30 ALLEN 1600 2 2 2

30 TURNER 1500 3 3 3

DEPTNO ENAME DEPT_SALES 薪资排名_跳号 薪资排名_同级同号 薪资排名_不跳号

---------- ---------- ---------- ------------- ----------------- ---------------

30 MARTIN 1250 4 4 4

30 WARD 1250 4 4 5

30 JAMES 950 6 5 6

已选择14行。

16.--分析函数使用 首尾记录查询

SQL> select min(empno) keep(dense_rank first order by sum(sal) desc nulls last)

薪资排名首位, max(empno) keep(dense_rank last order by sum(sal) desc nulls last

) 薪资排名尾位

2 from emp

3 where sal is not null

4 and deptno is not null

5 group by empno;

薪资排名首位 薪资排名尾位

------------ ------------

7839 7369

--17.分析函数使用 前后排名查询

SQL> select min(empno) keep(dense_rank first order by sum(sal) desc nulls last)

薪资排名首位, max(empno) keep(dense_rank last order by sum(sal) desc nulls last

) 薪资排名尾位

2 from emp

3 where sal is not null

4 and deptno is not null

5 group by empno;

薪资排名首位 薪资排名尾位

------------ ------------

7839 7369

--18.分析函数使用示例 层次查询

SQL> select *

2 from (select deptno,

3 empno,

4 ename,

5 sum(sal) dept_sales,

6 ntile(3) over(partition by deptno order by sum(sal) nulls la

st) rank_ration

7 from emp

8 where deptno is not null

9 group by deptno, empno, ename)

10 where rank_ration = 1;

DEPTNO EMPNO ENAME DEPT_SALES RANK_RATION

---------- ---------- ---------- ---------- -----------

10 7934 MILLER 1300 1

20 7369 SMITH 800 1

20 7876 ADAMS 1100 1

30 7900 JAMES 950 1

30 7654 MARTIN 1250 1

19.--范围统计查询

--范围查询是分析函数发挥其功能的重点,范围查询是指查询当前记录的前面或后面的记录进行统计,比如想知道

--员工史密斯的雇佣日期前10天和后10天新进员工的最高薪资,可以使用分析函数来实现这个功能

SQL> select empno,

2 --ename,

3 hiredate,

4 sal,

5 max(sal) over(order by hiredate rows between 10 preceding and curren

t row) "前10天入职最高薪资",

6 max(sal) over(order by hiredate rows between current row and 10 foll

owing) "后10天入职最高薪资"

7 from emp

8 where sal is not null;

EMPNO HIREDATE SAL 前10天入职最高薪资 后10天入职最高薪资

---------- -------------- ---------- ------------------ ------------------

7369 17-12月-80 800 800 5000

7499 20-2月 -81 1600 1600 5000

7521 22-2月 -81 1250 1600 5000

7566 02-4月 -81 2975 2975 5000

7698 01-5月 -81 2850 2975 5000

7782 09-6月 -81 2450 2975 5000

7844 08-9月 -81 1500 2975 5000

7654 28-9月 -81 1250 2975 5000

7839 17-11月-81 5000 5000 5000

7900 03-12月-81 950 5000 3000

7902 03-12月-81 3000 5000 3000

EMPNO HIREDATE SAL 前10天入职最高薪资 后10天入职最高薪资

---------- -------------- ---------- ------------------ ------------------

7934 23-1月 -82 1300 5000 3000

7788 19-4月 -87 3000 5000 3000

7876 23-5月 -87 1100 5000 1100

已选择14行。

--20.相邻记录比较

SQL> select ename,

2 hiredate,

3 deptno,

4 sal,

5 sal - prev_sal "与前面的差异",sal - next_sal "与后面的差异"

6 from (select ename,

7 hiredate,

8 sal,

9 deptno,

10 lag(sal, 1, 0) over(order by hiredate) as prev_sal,

11 lead(sal, 1, 0) over(order by hiredate) as next_sal

12 from emp

13 where deptno is not null

14 and sal is not null);

ENAME HIREDATE DEPTNO SAL 与前面的差异 与后面的差异

---------- -------------- ---------- ---------- ------------ ------------

SMITH 17-12月-80 20 800 800 -800

ALLEN 20-2月 -81 30 1600 800 350

WARD 22-2月 -81 30 1250 -350 -1725

JONES 02-4月 -81 20 2975 1725 125

BLAKE 01-5月 -81 30 2850 -125 400

CLARK 09-6月 -81 10 2450 -400 950

TURNER 08-9月 -81 30 1500 -950 250

MARTIN 28-9月 -81 30 1250 -250 -3750

KING 17-11月-81 10 5000 3750 4050

JAMES 03-12月-81 30 950 -4050 -2050

FORD 03-12月-81 20 3000 2050 1700

ENAME HIREDATE DEPTNO SAL 与前面的差异 与后面的差异

---------- -------------- ---------- ---------- ------------ ------------

MILLER 23-1月 -82 10 1300 -1700 -1700

SCOTT 19-4月 -87 20 3000 1700 1900

ADAMS 23-5月 -87 20 1100 -1900 1100

已选择14行。

21.--抑制重复

SQL> select *

2 from (select empno,

3 ename,

4 sal,

5 hiredate,

6 row_number() over(partition by extract(year from hiredate)

rder by empno) rn

7 from emp

8 where hiredate is not null

9 and extract(year from hiredate) in (1981, 19872, 1983))

10 where rn = 1;

EMPNO ENAME SAL HIREDATE RN

---------- ---------- ---------- -------------- ----------

7499 ALLEN 1600 20-2月 -81 1

22.--行列转换

SQL> select job,

2 empno,

3 ename,

4 row_number() over(partition by job order by ename) rb

5 from emp

6 where job is not null;

JOB EMPNO ENAME RB

--------- ---------- ---------- ----------

ANALYST 7902 FORD 1

ANALYST 7788 SCOTT 2

CLERK 7876 ADAMS 1

CLERK 7900 JAMES 2

CLERK 7934 MILLER 3

CLERK 7369 SMITH 4

MANAGER 7698 BLAKE 1

MANAGER 7782 CLARK 2

MANAGER 7566 JONES 3

PRESIDENT 7839 KING 1

SALESMAN 7499 ALLEN 1

JOB EMPNO ENAME RB

--------- ---------- ---------- ----------

SALESMAN 7654 MARTIN 2

SALESMAN 7844 TURNER 3

SALESMAN 7521 WARD 4

已选择14行。

说明:本人于ITEYE创建于2013年,现转移到CSDN
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: