- 浏览: 146922 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
陈碧滔:
java获取工程目录路径 -
stevenjohn:
楼主能上传一下源代码吗?
ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息 -
指挥家:
讲的很好!
Foxmail6收发Web mail邮箱邮件实现原理 -
azhqiang:
谢谢你啊。呵呵
flex最全的表单验证
注意这里有3条记录的订单总额是一样的。假如我们现在需要筛选排名前12位的客户,如果使用rownum会有什么样的后果呢?
SQL > select rownum, t. *
2 from ( select *
3 from user_order
4 order by customer_sales desc ) t
5 where rownum <= 12
6 order by customer_sales desc ;
ROWNUM REGION_ID CUSTOMER_ID CUSTOMER_SALES
-- -------- ---------- ----------- --------------
1 9 25 2232703
2 8 17 1944281
3 7 14 1929774
4 5 4 1878275
5 10 26 1808949
6 6 6 1788836
7 8 20 1413722
8 10 27 1322747
9 7 13 1310434
10 7 15 1255591
11 8 18 1253840
12 5 2 1224992
12 rows selected.
很明显假如只是简单地按rownum进行排序的话,我们漏掉了另外两条记录(参考上面的结果)。
二、使用分析函数来为记录排名:
针对上面的情况,Oracle从8i开始就提供了3个分析函数:rand,dense_rank,row_number来解决诸如此类的问题,下面我们来看看这3个分析函数的作用以及彼此之间的区别:
Rank,Dense_rank,Row_number函数为每条记录产生一个从1开始至N的自然数,N的值可能小于等于记录的总数。这3个函数的唯一区别在于当碰到相同数据时的排名策略。
①ROW_NUMBER:
Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
②DENSE_RANK:
Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。
③RANK:
Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
这样的介绍有点难懂,我们还是通过实例来说明吧,下面的例子演示了3个不同函数在遇到相同数据时不同排名策略:
SQL > select region_id, customer_id, sum (customer_sales) total,
2 rank() over ( order by sum (customer_sales) desc ) rank,
3 dense_rank() over ( order by sum (customer_sales) desc ) dense_rank,
4 row_number() over ( order by sum (customer_sales) desc ) row_number
5 from user_order
6 group by region_id, customer_id;
REGION_ID CUSTOMER_ID TOTAL RANK DENSE_RANK ROW_NUMBER
-- -------- ----------- ---------- ---------- ---------- ----------
8 18 1253840 11 11 11
5 2 1224992 12 12 12
9 23 1224992 12 12 13
9 24 1224992 12 12 14
10 30 1216858 15 13 15
30 rows selected.
请注意上面的绿色高亮部分,这里生动的演示了3种不同的排名策略:
①对于第一条相同的记录,3种函数的排名都是一样的:12
②当出现第二条相同的记录时,Rank和Dense_rank依然给出同样的排名12;而row_number则顺延递增为13,依次类推至第三条相同的记录
③当排名进行到下一条不同的记录时,可以看到Rank函数在12和15之间空出了13,14的排名,因为这2个排名实际上已经被第二、三条相同的记录占了。而Dense_rank则顺序递增。row_number函数也是顺序递增
比较上面3种不同的策略,我们在选择的时候就要根据客户的需求来定夺了:
①假如客户就只需要指定数目的记录,那么采用row_number是最简单的,但有漏掉的记录的危险
②假如客户需要所有达到排名水平的记录,那么采用rank或dense_rank是不错的选择。至于选择哪一种则看客户的需要,选择dense_rank或得到最大的记录
三、使用分析函数为记录进行分组排名:
上面的排名是按订单总额来进行排列的,现在跟进一步:假如是为各个地区的订单总额进行排名呢?这意味着又多了一次分组操作:对记录按地区分组然后进行排名。幸亏Oracle也提供了这样的支持,我们所要做的仅仅是在over函数中order by的前面增加一个分组子句:partition by region_id。
SQL > select region_id, customer_id,
sum (customer_sales) total,
2 rank() over (partition by region_id
order by sum (customer_sales) desc ) rank,
3 dense_rank() over (partition by region_id
order by sum (customer_sales) desc ) dense_rank,
4 row_number() over (partition by region_id
order by sum (customer_sales) desc ) row_number
5 from user_order
6 group by region_id, customer_id;
REGION_ID CUSTOMER_ID TOTAL RANK DENSE_RANK ROW_NUMBER
-- -------- ----------- ---------- ---------- ---------- ----------
5 4 1878275 1 1 1
5 2 1224992 2 2 2
5 5 1169926 3 3 3
6 6 1788836 1 1 1
6 9 1208959 2 2 2
6 10 1196748 3 3 3
30 rows selected.
现在我们看到的排名将是基于各个地区的,而非所有区域的了!Partition by 子句在排列函数中的作用是将一个结果集划分成几个部分,这样排列函数就能够应用于这各个子集。
三.分析函数3(top\bottom n、first\last、ntile)
目录
===============================================
1.带空值的排列
2.Top/Bottom N查询
3.First/Last排名查询
4.按层次查询
一、带空值的排列:
在前面《Oracle开发专题之:分析函数2(Rank、Dense_rank、row_number) 》一文中,我们已经知道了如何为一批记录进行全排列、分组排列。假如被排列的数据中含有空值呢?
SQL > select region_id, customer_id,
2 sum (customer_sales) cust_sales,
3 sum ( sum (customer_sales)) over (partition by region_id) ran_total,
4 rank() over (partition by region_id
5 order by sum (customer_sales) desc ) rank
6 from user_order
7 group by region_id, customer_id;
REGION_ID CUSTOMER_ID CUST_SALES RAN_TOTAL RANK
-- -------- ----------- ---------- ---------- ----------
10 31 6238901 1
10 26 1808949 6238901 2
10 27 1322747 6238901 3
10 30 1216858 6238901 4
10 28 986964 6238901 5
10 29 903383 6238901 6
我们看到这里有一条记录的CUST_TOTAL字段值为NULL,但居然排在第一名了!显然这不符合情理。所以我们重新调整完善一下我们的排名策略,看看下面的语句:
SQL > select region_id, customer_id,
2 sum (customer_sales) cust_total,
3 sum ( sum (customer_sales)) over (partition by region_id) reg_total,
4 rank() over (partition by region_id
order by sum (customer_sales) desc NULLS LAST ) rank
5 from user_order
6 group by region_id, customer_id;
REGION_ID CUSTOMER_ID CUST_TOTAL REG_TOTAL RANK
-- -------- ----------- ---------- ---------- ----------
10 26 1808949 6238901 1
10 27 1322747 6238901 2
10 30 1216858 6238901 3
10 28 986964 6238901 4
10 29 903383 6238901 5
10 31 6238901 6
绿色高亮处,NULLS LAST/FIRST告诉Oracle让空值排名最后后第一。
注意是NULLS,不是NULL。
二、Top/Bottom N查询:
在日常的工作生产中,我们经常碰到这样的查询:找出排名前5位的订单客户、找出排名前10位的销售人员等等。现在这个对我们来说已经是很简单的问题了。下面我们用一个实际的例子来演示:
【1】找出所有订单总额排名前3的大客户:
SQL > select *
SQL > from ( select region_id,
SQL > customer_id,
SQL > sum (customer_sales) cust_total,
SQL > rank() over ( order by sum (customer_sales) desc NULLS LAST) rank
SQL > from user_order
SQL > group by region_id, customer_id)
SQL > where rank <= 3 ;
REGION_ID CUSTOMER_ID CUST_TOTAL RANK
-- -------- ----------- ---------- ----------
9 25 2232703 1
8 17 1944281 2
7 14 1929774 3
SQL >
SQL > select rownum, t. *
2 from ( select *
3 from user_order
4 order by customer_sales desc ) t
5 where rownum <= 12
6 order by customer_sales desc ;
ROWNUM REGION_ID CUSTOMER_ID CUSTOMER_SALES
-- -------- ---------- ----------- --------------
1 9 25 2232703
2 8 17 1944281
3 7 14 1929774
4 5 4 1878275
5 10 26 1808949
6 6 6 1788836
7 8 20 1413722
8 10 27 1322747
9 7 13 1310434
10 7 15 1255591
11 8 18 1253840
12 5 2 1224992
12 rows selected.
很明显假如只是简单地按rownum进行排序的话,我们漏掉了另外两条记录(参考上面的结果)。
二、使用分析函数来为记录排名:
针对上面的情况,Oracle从8i开始就提供了3个分析函数:rand,dense_rank,row_number来解决诸如此类的问题,下面我们来看看这3个分析函数的作用以及彼此之间的区别:
Rank,Dense_rank,Row_number函数为每条记录产生一个从1开始至N的自然数,N的值可能小于等于记录的总数。这3个函数的唯一区别在于当碰到相同数据时的排名策略。
①ROW_NUMBER:
Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
②DENSE_RANK:
Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。
③RANK:
Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
这样的介绍有点难懂,我们还是通过实例来说明吧,下面的例子演示了3个不同函数在遇到相同数据时不同排名策略:
SQL > select region_id, customer_id, sum (customer_sales) total,
2 rank() over ( order by sum (customer_sales) desc ) rank,
3 dense_rank() over ( order by sum (customer_sales) desc ) dense_rank,
4 row_number() over ( order by sum (customer_sales) desc ) row_number
5 from user_order
6 group by region_id, customer_id;
REGION_ID CUSTOMER_ID TOTAL RANK DENSE_RANK ROW_NUMBER
-- -------- ----------- ---------- ---------- ---------- ----------
8 18 1253840 11 11 11
5 2 1224992 12 12 12
9 23 1224992 12 12 13
9 24 1224992 12 12 14
10 30 1216858 15 13 15
30 rows selected.
请注意上面的绿色高亮部分,这里生动的演示了3种不同的排名策略:
①对于第一条相同的记录,3种函数的排名都是一样的:12
②当出现第二条相同的记录时,Rank和Dense_rank依然给出同样的排名12;而row_number则顺延递增为13,依次类推至第三条相同的记录
③当排名进行到下一条不同的记录时,可以看到Rank函数在12和15之间空出了13,14的排名,因为这2个排名实际上已经被第二、三条相同的记录占了。而Dense_rank则顺序递增。row_number函数也是顺序递增
比较上面3种不同的策略,我们在选择的时候就要根据客户的需求来定夺了:
①假如客户就只需要指定数目的记录,那么采用row_number是最简单的,但有漏掉的记录的危险
②假如客户需要所有达到排名水平的记录,那么采用rank或dense_rank是不错的选择。至于选择哪一种则看客户的需要,选择dense_rank或得到最大的记录
三、使用分析函数为记录进行分组排名:
上面的排名是按订单总额来进行排列的,现在跟进一步:假如是为各个地区的订单总额进行排名呢?这意味着又多了一次分组操作:对记录按地区分组然后进行排名。幸亏Oracle也提供了这样的支持,我们所要做的仅仅是在over函数中order by的前面增加一个分组子句:partition by region_id。
SQL > select region_id, customer_id,
sum (customer_sales) total,
2 rank() over (partition by region_id
order by sum (customer_sales) desc ) rank,
3 dense_rank() over (partition by region_id
order by sum (customer_sales) desc ) dense_rank,
4 row_number() over (partition by region_id
order by sum (customer_sales) desc ) row_number
5 from user_order
6 group by region_id, customer_id;
REGION_ID CUSTOMER_ID TOTAL RANK DENSE_RANK ROW_NUMBER
-- -------- ----------- ---------- ---------- ---------- ----------
5 4 1878275 1 1 1
5 2 1224992 2 2 2
5 5 1169926 3 3 3
6 6 1788836 1 1 1
6 9 1208959 2 2 2
6 10 1196748 3 3 3
30 rows selected.
现在我们看到的排名将是基于各个地区的,而非所有区域的了!Partition by 子句在排列函数中的作用是将一个结果集划分成几个部分,这样排列函数就能够应用于这各个子集。
三.分析函数3(top\bottom n、first\last、ntile)
目录
===============================================
1.带空值的排列
2.Top/Bottom N查询
3.First/Last排名查询
4.按层次查询
一、带空值的排列:
在前面《Oracle开发专题之:分析函数2(Rank、Dense_rank、row_number) 》一文中,我们已经知道了如何为一批记录进行全排列、分组排列。假如被排列的数据中含有空值呢?
SQL > select region_id, customer_id,
2 sum (customer_sales) cust_sales,
3 sum ( sum (customer_sales)) over (partition by region_id) ran_total,
4 rank() over (partition by region_id
5 order by sum (customer_sales) desc ) rank
6 from user_order
7 group by region_id, customer_id;
REGION_ID CUSTOMER_ID CUST_SALES RAN_TOTAL RANK
-- -------- ----------- ---------- ---------- ----------
10 31 6238901 1
10 26 1808949 6238901 2
10 27 1322747 6238901 3
10 30 1216858 6238901 4
10 28 986964 6238901 5
10 29 903383 6238901 6
我们看到这里有一条记录的CUST_TOTAL字段值为NULL,但居然排在第一名了!显然这不符合情理。所以我们重新调整完善一下我们的排名策略,看看下面的语句:
SQL > select region_id, customer_id,
2 sum (customer_sales) cust_total,
3 sum ( sum (customer_sales)) over (partition by region_id) reg_total,
4 rank() over (partition by region_id
order by sum (customer_sales) desc NULLS LAST ) rank
5 from user_order
6 group by region_id, customer_id;
REGION_ID CUSTOMER_ID CUST_TOTAL REG_TOTAL RANK
-- -------- ----------- ---------- ---------- ----------
10 26 1808949 6238901 1
10 27 1322747 6238901 2
10 30 1216858 6238901 3
10 28 986964 6238901 4
10 29 903383 6238901 5
10 31 6238901 6
绿色高亮处,NULLS LAST/FIRST告诉Oracle让空值排名最后后第一。
注意是NULLS,不是NULL。
二、Top/Bottom N查询:
在日常的工作生产中,我们经常碰到这样的查询:找出排名前5位的订单客户、找出排名前10位的销售人员等等。现在这个对我们来说已经是很简单的问题了。下面我们用一个实际的例子来演示:
【1】找出所有订单总额排名前3的大客户:
SQL > select *
SQL > from ( select region_id,
SQL > customer_id,
SQL > sum (customer_sales) cust_total,
SQL > rank() over ( order by sum (customer_sales) desc NULLS LAST) rank
SQL > from user_order
SQL > group by region_id, customer_id)
SQL > where rank <= 3 ;
REGION_ID CUSTOMER_ID CUST_TOTAL RANK
-- -------- ----------- ---------- ----------
9 25 2232703 1
8 17 1944281 2
7 14 1929774 3
SQL >
发表评论
-
Oracle导出导入dmp文件(转)
2010-11-17 13:41 4611Oracle数据导入导出imp/exp ... -
row_number over(partition by col1 order by col2)
2010-10-28 11:16 1843row_number() OVER (PARTITION BY ... -
orcle中sys_connect_by_path的用法
2010-10-28 10:21 941sys_connect_by_path的几种 ... -
使用plsql一些常见的操作
2010-09-01 23:51 957/**创建一个访问分析表*/ create table Ac ... -
PL/SQL编程简介(转)
2010-08-12 11:24 764Oracle在数据库中引入了一种过程化编程语言,称为PL/SQ ... -
oracle函数手册(带示例)
2010-07-30 15:12 730oracle函数手册 SQL中的单记录函数 1.ASCII 返 ... -
Oracle分析函数参考手册[下][转载自JavaEye]
2010-07-30 15:08 795=============================== ... -
Oracle分析函数参考手册[上][转载自JavaEye]
2010-07-30 15:07 742=============================== ... -
Oracle 分析函数的使用(zt)
2010-07-30 15:07 6452/11/2005 09:43 FPOracle 分析函数使用 ... -
Oracle分析函数参考手册
2010-07-30 15:06 65722/06/2005 12:22 FP Oracle从8.1. ... -
Oracle函数列表速查
2010-07-30 15:03 635PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数 ... -
oracle分析函数(3)
2010-07-30 14:59 746【2】找出每个区域订单总额排名前3的大客户: SQL &g ... -
oracle分析函数(1)
2010-07-30 14:57 688一.分析函数(OVER) 目录: ============ ... -
用SQL语句添加删除修改字段
2010-07-27 14:19 1328增加字段alter table docdsp add dsp ... -
oracle 存储过程的基本语法
2010-07-13 18:57 6591.基本结构 CREATE OR REPLACE PROCED ... -
oracle 字符串连接
2010-06-28 15:26 841字符串连接 SQL> select 'abc' || ' ... -
系统重装后,oracle数据库中数据快速恢复
2010-06-18 15:56 14511. 准备工作把旧的ORACLE所有文件都COPY备份下来 ... -
SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
2010-06-06 19:05 754Insert是T-sql中常用语句,Insert ... -
Oracle字符串处理函数
2010-06-02 19:27 1285项目中有涉及存储过程对字符串的处理,所以就将在网上查找到的资料 ...
相关推荐
关于ORACLE分析函数的教程,教程描述描述清晰
ORACLE 分析函数大全,包含很多关于ORACLE的分析函数,内置函数
文档详细介绍了oracle的分析函数,包括功能说明、sql示例等。分析函数功能强大,在报表或数据迁移的时候可能会使用到。分析函数用法看上去有点复杂,最好使用的时候,参考文档
ORACLE分析函数.pdf
Oracle分析函数.doc
oracle 分析函数 开发必备 数据库开发工程师
Oracle 分析函数详解 1. 自动汇总函数rollup,cube, 2. rank 函数, rank,dense_rank,row_number 3. lag,lead函数 4. sum,avg,的移动增加,移动平均数 5. ratio_to_report报表处理函数 6. first,last取基数的分析函数
Oracle分析函数使用总结Oracle分析函数使用总结Oracle分析函数使用总结Oracle分析函数使用总结
oracle分析函数(用法+实例),这属于oracle的高级应用。
Oracle分析函数,常用分析函数应有尽有
分析函数是oracle中强大的功能,附件是分析函数学习笔记
分析函数2(Rank, Dense_rank, row_number);分析函数3(Top/Bottom N、First/Last、NTile);窗口函数;报表函数;分析函数总结;26个分析函数;PLSQL开发笔记和小结;分析函数简述 ROW_NUMBER () OVER([partition_clause]...
Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行。
ORACLE分析函数大全 包括大部分常用的分析函数
oracle分析函数,窗口函数,报表函数 分析函数(OVER) 分析函数2(Rank, Dense_rank, row_number) 分析函数3(Top/Bottom N、First/Last、NTile)
Oracle分析函数.pdf,这份资料详细介绍了Oracle分析函数的使用,Oracle分析函数.pdf是一份不错的文档
NULL 博文链接:https://yangkai.iteye.com/blog/754447
Oracle分析函数,常见的基本统计函数里面都有,大家可以通过安装Oracle的示例数据库来一步一步跟进学习!