oracle分析函数(3)

【2】找出每个区域订单总额排名前3的大客户:

SQL >   select   *
  
2      from  ( select  region_id,
  
3                  customer_id,
  
4                   sum (customer_sales) cust_total,
  
5                   sum ( sum (customer_sales))  over (partition  by  region_id) reg_total,
  
6                  rank() over (partition  by  region_id
                               
order   by   sum (customer_sales)  desc  NULLS LAST) rank
   7              from  user_order
  
8             group   by  region_id, customer_id)
  
9     where rank  <=   3 ;

 REGION_ID CUSTOMER_ID CUST_TOTAL  REG_TOTAL       RANK
-- -------- ----------- ---------- ---------- ----------
          5             4      1878275      5585641            1
         
5             2      1224992      5585641            2
         
5             5      1169926      5585641            3
         
6             6      1788836      6307766            1
         
6             9      1208959      6307766            2
         
6            10      1196748      6307766            3
         
7            14      1929774      6868495            1
         
7            13      1310434      6868495            2
         
7            15      1255591      6868495            3
         
8            17      1944281      6854731            1
         
8            20      1413722      6854731            2
         
8            18      1253840      6854731            3
         
9            25      2232703      6739374            1
         
9            23      1224992      6739374            2
         
9            24      1224992      6739374            2
        
10            26      1808949      6238901            1
        
10            27      1322747      6238901            2
        
10            30      1216858      6238901            3

18  rows selected.


三、First/Last排名查询:

想象一下下面的情形:找出订单总额最多、最少的客户。按照前面我们学到的知识,这个至少需要2个查询。第一个查询按照订单总额降序排列以期拿到第一名,第 二个查询按照订单总额升序排列以期拿到最后一名。是不是很烦?因为Rank函数只告诉我们排名的结果,却无法自动替我们从中筛选结果。

幸好Oracle为我们在排列函数之外提供了两个额外的函数:first、last函数,专门用来解决这种问题。还是用实例说话:

SQL >   select   min(customer_id)
   2          keep (dense_rank first  order   by   sum (customer_sales)  desc ) first,
  
3           min (customer_id)
  
4          keep (dense_rank last  order   by   sum (customer_sales)  desc last
  
5      from  user_order
  
6     group   by  customer_id;

     FIRST       LAST
-- -------- ----------
         31            1


这里有几个看起来比较疑惑的地方:

①为什么这里要用min函数
②Keep这个东西是干什么的
③fist/last是干什么的
④dense_rank和dense_rank()有什么不同,能换成rank吗?

首先解答一下第一个问题:min函数的作用是用于当存在多个First/Last情况下保证返回唯一的记录。假如我们去掉会有什么样的后果呢?

SQL >   select  keep (dense_rank first  order   by   sum (customer_sales)  desc ) first, 
  
2              keep (dense_rank last  order   by   sum (customer_sales)  desc ) last
  
3      from  user_order
  
4     group   by  customer_id;
select  keep (dense_rank first  order   by   sum (customer_sales)  desc ) first,
                        
*
ERROR at line 
1 :
ORA
- 00907 : missing  right  parenthesis


接下来看看第2个问题:keep是干什么用的?从上面的结果我们已经知道Oracle对排名的结果只“保留”2条数据,这就是keep的作用。告诉Oracle只保留符合keep条件的记录。

那么什么才是符合条件的记录呢?这就是第3个问题了。dense_rank是告诉Oracle排列的策略,first/last则告诉最终筛选的条件。

第4个问题:如果我们把dense_rank换成rank呢?

SQL >   select   min (region_id)
  
2           keep(rank first  order   by   sum (customer_sales)  desc ) first,
  
3           min (region_id)
  
4           keep(rank last  order   by   sum (customer_sales)  desc ) last
  
5      from  user_order
  
6     group   by  region_id;
select   min (region_id)
*
ERROR at line 
1 :
ORA
- 02000 : missing DENSE_RANK


四、按层次查询:

现在我们已经见识了如何通过Oracle的分析函数来获取Top/Bottom N,第一个,最后一个记录。有时我们会收到类似下面这样的需求:找出订单总额排名前1/5的客户。

很熟悉是不?我们马上会想到第二点中提到的方法,可是rank函数只为我们做好了排名,并不知道每个排名在总排名中的相对位置,这时候就引入了另外一个分析函数NTile,下面我们就以上面的需求为例来讲解一下:

SQL >   select  region_id,
  
2          customer_id,
  
3          ntile( 5 over ( order   by   sum (customer_sales)  desc ) til
  
4      from  user_order
  
5     group   by  region_id, customer_id;

 REGION_ID CUSTOMER_ID       TILE
-- -------- ----------- ----------
         10            31            1
         
9            25            1
        
10            26            1
         
6             6             1          
         
8            18            2
         
5             2             2
         
9            23            3
         
6             9             3
         
7            11            3
         
5             3             4
         
6             8             4
         
8            16            4
         
6             7             5
        
10            29            5
         
5             1             5


Ntil函数为各个记录在记录集中的排名计算比例,我们看到所有的记录被分成5个等级,那么假如我们只需要前1/5的记录则只需要截取TILE的值为1的记录就可以了。假如我们需要排名前25%的记录(也就是1/4)那么我们只需要设置ntile(4)就可以了。

参考资料:《Mastering Oracle SQL》(By Alan Beaulieu , Sanjay Mishra  O'Reilly June 2004  0-596-00632-2)
博客:http://www.blogjava.net/pengpenglin/archive/2008/06/25/210536.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle分析函数——函数列表 SUM :该函数计算组中表达式的累积和 MIN :在一个组中的数据窗口中查找表达式的最小 MAX :在一个组中的数据窗口中查找表达式的最大 AVG :用于计算一个组和数据窗口内表达式的平均。 COUNT :对一组内发生的事情进行累积计数 ------------------------------------------------------------------------------------------------- RANK :根据ORDER BY子句中表达式的,从查询返回的每一行,计算它们与其它行的相对位置 DENSE_RANK :根据ORDER BY子句中表达式的,从查询返回的每一行,计算它们与其它行的相对位置 FIRST :从DENSE_RANK返回的集合中取出排在最面的一个的行 LAST :从DENSE_RANK返回的集合中取出排在最后面的一个的行 FIRST_VALUE :返回组中数据窗口的第一个 LAST_VALUE :返回组中数据窗口的最后一个。 LAG :可以访问结果集中的其它行而不用进行自连接 LEAD :LEAD与LAG相反,LEAD可以访问组中当行之后的行 ROW_NUMBER :返回有序组中一行的偏移量,从而可用于按特定标准排序的行号 ------------------------------------------------------------------------------------------------- STDDEV :计算行关于组的标准偏离 STDDEV_POP:该函数计算体标准偏离,并返回体变量的平方根 STDDEV_SAMP:该函数计算累积样本标准偏离,并返回体变量的平方根 VAR_POP :该函数返回非空集合的体变量(忽略null) VAR_SAMP :该函数返回非空集合的样本变量(忽略null) VARIANCE :如果表达式中行数为1,则返回0,如果表达式中行数大于1,则返回VAR_SAMP COVAR_POP :返回一对表达式的体协方差 COVAR_SAMP :返回一对表达式的样本协方差 CORR :返回一对表达式的相关系数 ------------------------------------------------------------------------------------------------- CUME_DIST :计算一行在组中的相对位置 NTILE :将一个组分为"表达式"的散列表示 PERCENT_RANK :和CUME_DIST(累积分配)函数类似 PERCENTILE_DISC :返回一个与输入的分布百分比相对应的数据 PERCENTILE_CONT :返回一个与输入的分布百分比相对应的数据 RATIO_TO_REPORT :该函数计算expression/(sum(expression))的,它给出相对于数的百分比 REGR_ (Linear Regression) Functions :这些线性回归函数适合最小二乘法回归线,有9个不同的回归函数可使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值