(1)rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
(2)dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。
(3)row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
(4)ntile是要把查询得到的结果平均分为几组,如果不平均则分给第一组。

例如:

create table s_score
( s_id number(6)
,score number(4,2)
);
insert into s_score values(001,98);
insert into s_score values(002,66.5);
insert into s_score values(003,99);
insert into s_score values(004,98);
insert into s_score values(005,98);
insert into s_score values(006,80); select
s_id
,score
,rank() over(order by score desc) rank --按照成绩排名,纯排名
,dense_rank() over(order by score desc) dense_rank --按照成绩排名,相同成绩排名一致
,row_number() over(order by score desc) row_number --按照成绩依次排名
,ntile(3) over (order by score desc) group_s --按照分数划分成绩梯队
from s_score;

排名/排序的时候,有时候,我们会想到利用伪列row_num,利用row_num确实可以解决某些场景下的问题(但是相对也比较复杂),而且有些场景下的问题却很难解决。

例:取成绩前三名,并且前三名含有并列的情况。通过上面例子,我们可以直观的看到,结果应该有5条记录:

select
s_id
,score
,dense_rank
from (
select
s_id
,score
,rank() over(order by score desc) rank
,dense_rank() over(order by score desc) dense_rank
,row_number() over(order by score desc) row_number
from s_score
) t
where dense_rank <= 3; S_ID SCORE DENSE_RANK
------- ------ ----------
3 99.00 1
1 98.00 2
5 98.00 2
4 98.00 2
6 80.00 3

如果只是简单的想到去用rownum <= 3 得到的结果显然不可能是正确的。

组内的排名或者排序是经常遇到的一种场景。
例如,取每个销售部门内,销售业绩最好的前三名。取每个班级内成绩排名信息等等..
取每个班级内每门课成绩排名第一的同学信息:

drop table S_SCORE;
create table S_SCORE
(
S_ID NUMBER(6),
CLASS_ID VARCHAR2(2),
COURSE VARCHAR2(20),
SCORE NUMBER(5,2)
); INSERT INTO S_SCORE VALUES(1001,'A','MATH','');
INSERT INTO S_SCORE VALUES(1004,'B','MATH','');
INSERT INTO S_SCORE VALUES(1002,'A','MATH','');
INSERT INTO S_SCORE VALUES(1003,'A','MATH','');
INSERT INTO S_SCORE VALUES(1001,'B','MATH','');
INSERT INTO S_SCORE VALUES(1001,'B','MATH','');
INSERT INTO S_SCORE VALUES(1001,'A','ORACLE','');
INSERT INTO S_SCORE VALUES(1004,'B','ORACLE','');
INSERT INTO S_SCORE VALUES(1002,'A','ORACLE','');
INSERT INTO S_SCORE VALUES(1003,'A','ORACLE','');
INSERT INTO S_SCORE VALUES(1001,'B','ORACLE','');
INSERT INTO S_SCORE VALUES(1001,'B','ORACLE',''); select
s_id
,class_id
,course
,score
,dense_rank() over (partition by class_id,course order by score desc) drk
from S_SCORE; S_ID CLASS_ID COURSE SCORE DRK
------- -------- -------------------- ------- ----------
1002 A MATH 99.00 1
1001 A MATH 67.00 2
1003 A MATH 55.00 3
1001 A ORACLE 97.00 1
1002 A ORACLE 79.00 2
1003 A ORACLE 65.00 3
1004 B MATH 88.00 1
1001 B MATH 88.00 1
1001 B MATH 70.00 2
1001 B ORACLE 82.00 1
1001 B ORACLE 78.00 2
1004 B ORACLE 48.00 3 select
s_id
,class_id
,course
,score
from (
select
s_id
,class_id
,course
,score
,dense_rank() over (partition by class_id,course order by score desc) drk
from S_SCORE
) t
where drk = 1; S_ID CLASS_ID COURSE SCORE
------- -------- -------------------- -------
1002 A MATH 99.00
1001 A ORACLE 97.00
1004 B MATH 88.00
1001 B MATH 88.00
1001 B ORACLE 82.00

rank()和dense_rank()用法相似,这里就不在举例说明了。可以将上面的例子中dense_rank()替换成rank()实现。

接下来,看一个使用row_number()的场景
例:查看每个部门最近一笔销售记录:

select * from criss_sales order by dept_id,sale_date desc;

DEPT_ID SALE_DATE   GOODS_TYPE    SALE_CNT
------- ----------- ---------- -----------
D01 2014/5/4 G02 80
D01 2014/4/30 G03 800
D01 2014/4/8 G01 200
D01 2014/3/4 G00 700
D02 2014/5/2 G03 900
D02 2014/4/27 G01 300
D02 2014/4/8 G02 100
D02 2014/3/6 G00 500

即,我们希望得到这两条记录:

D01     2014/5/4    G02                 80
D02 2014/5/2 G03 900
select
dept_id
,sale_date
,goods_type
,sale_cnt
,row_number() over (partition by dept_id order by sale_date desc)
from criss_sales; DEPT_ID SALE_DATE GOODS_TYPE SALE_CNT ROW_NUMBER()OVER(PARTITIONBYDE
------- ----------- ---------- ----------- ------------------------------
D01 2014/5/4 G02 80 1
D01 2014/4/30 G03 800 2
D01 2014/4/8 G01 200 3
D01 2014/3/4 G00 700 4
D02 2014/5/2 G03 900 1
D02 2014/4/27 G01 300 2
D02 2014/4/8 G02 100 3
D02 2014/3/6 G00 500 4 select
dept_id
,sale_date
,goods_type
,sale_cnt
from (
select
dept_id
,sale_date
,goods_type
,sale_cnt
,row_number() over (partition by dept_id order by sale_date desc) rn
from criss_sales
) t
where rn = 1; DEPT_ID SALE_DATE GOODS_TYPE SALE_CNT
------- ----------- ---------- -----------
D01 2014/5/4 G02 80
D02 2014/5/2 G03 900

有时会有这样的需求:如果数据排序后分为三部分,业务人员只关心其中的一部分,如何将这中间的三分之一数据拿出来呢?
这时比较好的选择,就是使用ntile函数:

select
dept_id
,sale_date
,goods_type
,sale_cnt
,ntile(3) over (order by sale_cnt desc nulls last) all_cmp
,ntile(3) over (partition by dept_id order by sale_cnt desc nulls last) all_dept
from criss_sales;

可以看到,Ntile函数为各个记录在记录集中的排名计算比例,返回每条记录所在集合比例位置的值。
例如我们关心全公司前三分之一部分的数据,只需选择 ALL_CMP = 1 的数据就可以了;
如果只是关心全公司中间的三分之一数据,只需选择 ALL_CMP = 2 的数据就可以了。

Oracle分析函数-排序排列(rank、dense_rank、row_number、ntile)的更多相关文章

  1. Oracle 的开窗函数 rank,dense_rank,row_number

    1.开窗函数和分组函数的区别 分组函数是指按照某列或者某些列分组后进行某种计算,比如计数,求和等聚合函数进行计算. 开窗函数是指基于某列或某些列让数据有序,数据行数和原始数据数相同,依然能曾现个体数据 ...

  2. [转]oracle分析函数Rank, Dense_rank, row_number

    oracle分析函数Rank, Dense_rank, row_number 分析函数2(Rank, Dense_rank, row_number)   目录 ==================== ...

  3. oracle分析函数Rank, Dense_rank, row_number

    http://www.cnblogs.com/wuyisky/archive/2010/02/24/oracle_rank.html 目录=============================== ...

  4. Oracle分析函数 — rank, dense_rank, row_number用法

    本文通过例子演示了Oracle分析函数 —— rank, dense_rank, row_number的用法. //首先建score表 create table score( course   nva ...

  5. rank,dense_rank,row_number使用和区别

    rank,dense_rank,row_number区别 一:语法(用法):     rank() over([partition by col1] order by col2)      dense ...

  6. 【DB2】DB2中rank(),dense_rank(),row_number()的用法

    1.准备测试数据 DROP TABLE oliver_1; ),SUB_NO ),SCORE int); ,,); ,,); ,,); ,,); ,,); ,,); 2.详解rank(),dense_ ...

  7. oracle sql rank dense_rank row_number fisrt last

    測試表emp

  8. [z]一个SQL语句分清楚RANK(),DENSE_RANK(),ROW_NUMBER()三个排序的不同

    转自:http://blog.csdn.net/s630730701/article/details/51902762 在SCOTT用户下,执行下面SQL; SELECT s.deptno,s.ena ...

  9. 关于sql row_number,rank,dense_rank,ntile函数

    row_number排序最好用它,它依次排名,不出现相同名次,如:1,2,3,4,5 rank出现相同排名,且跳过相同的排名号排下一名,如:1,1,3,4,5, dense_rank出现相同排名,不跳 ...

随机推荐

  1. Bzoj4598: [Sdoi2016]模式字符串 点分治 哈希

    国际惯例的题面:这种关于树上路径的题,我也没什么好办法,只好点分治.考虑当前分治重心为root,如何统计经过分治重心的路径的答案.我们令prf[i]表示某个点到root的路径(不含root)已经循环匹 ...

  2. 20172302《程序设计与数据结构》实验三 敏捷开发与XP实践报告

    课程:<程序设计与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年5月16日 必修/选修: 必修 1.实验内容 (1)代码规 ...

  3. 关于C#报空Object is null 错误的看法

    昨天项目的一个问题 :在切换场景页面的时候,报空指针的错,总显示没有找到对象.由于代码是之前就早写好的了,只是根据最上层领导的意见修改下个别显示UI,所以也就一定是后来的那些代码问题.果不其然,加的新 ...

  4. MYSQL时间类别总结: TIMESTAMP、DATETIME、DATE、TIME、YEAR

    总结背景: 对于MYSQL数据库日期类型或多有了解, 但并很清晰其中一些规则. 基本都是面向浏览器编码, 这实质上也是一种方式.  但期间遇到两个问题: 时常遇到建表中出现多个datetime或者ti ...

  5. dockerfile安装php遇到的坑

    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpi ...

  6. C#轻量级日志监控器EasyLogMonitor

    一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理和 ...

  7. Knockout.Js官网学习(selectedOptions绑定、uniqueName 绑定)

    selectedOptions绑定 selectedOptions绑定用于控制multi-select列表已经被选择的元素,用在使用options绑定的<select>元素上. 当用户在m ...

  8. 【NIO】Java NIO之缓冲

    一.前言 在笔者打算学习Netty框架时,发现很有必要先学习NIO,因此便有了本博文,首先介绍的是NIO中的缓冲. 二.缓冲 2.1 层次结构图 除了布尔类型外,其他基本类型都有相对应的缓冲区类,其继 ...

  9. Grails 第一课

    package helloworld import org.junit.*; import java.util.*; class HelloController { def index() { //d ...

  10. 3728 联合权值[NOIP 2014 Day1 T2]

    来源:NOIP2014 Day1 T2 OJ链接: http://codevs.cn/problem/3728/ https://www.luogu.org/problemnew/show/P1351 ...