比较有用的函数

wmsys.wm_concat();行转列。多行合并用“,”分割。

select t.user_id,wmsys.wm_concat(r.role_name) over(partition by t.user_id order by r.role_name asc) from t_user_role t,t_role r

where t.role_id = r.role_id

rank()、dense_rank()、row_number()分析函数

Rank,Dense_rank,Row_number函数为每条记录产生一个从1开始至N的自然数,N的值可能小于等于记录的总数。这3个函数的唯一区别在于当碰到相同数据时的排名策略。

①ROW_NUMBER:

Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。 

②DENSE_RANK:
Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。 

③RANK:
Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。

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

 

注意:带空值的排名,默认是第一的。

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让空值排名最后后第一。

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函数,常用函数,wmsys)