ysu_dong

导航

 
 

 

有些时候我们希望得到指定数据中的前n列,示例如下:

得到每个部门薪水最高的三个雇员:

先创建示例表

create table emp
as
select * from scott.emp;

alter table emp
add constraint emp_pk
primary key(empno);

create table dept
as
select * from scott.dept;

alter table dept
add constraint dept_pk
primary key(deptno);

先看一下row_number() /rank()/dense_rank()三个函数之间的区别

 select emp.deptno,emp.sal,emp.empno,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2

结果如下:

10    5000.00    7839    1    1    1
10    2450.00    7782    2    2    2
10    1300.00    7934    3    3    3
20    3000.00    7788    1    1    1
20    3000.00    7902    2    1    1
20    2975.00    7566    3    3    2
20    1100.00    7876    4    4    3
20    800.00    7369    5    5    4
30    2850.00    7698    1    1    1
30    1600.00    7499    2    2    2

取每个部门的薪水前三位雇员:

select t.deptno,t.rank,t.sal from
 (
 
select emp.*,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
 ) t
where t.rank<=3

结果如下:

10    1    5000.00
10    2    2450.00
10    3    1300.00
20    1    3000.00
20    1    3000.00
20    3    2975.00
30    1    2850.00
30    2    1600.00
30    3    1500.00

如果想输出成deptno  sal1   sal2   sal3这种类型的格式
步骤一(decode):

select t.deptno,decode(row_number,1,sal) sal1,decode(row_number,2,sal) sal2,decode(row_number,3,sal) sal3 from
 (
 
select emp.*,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
 ) t
where t.rank<=3

结果如下:

10    5000        
10                  2450    
10                             1300
20    3000        
20                  3000    
20                              2975
30    2850        
30                 1600    
30                             1500

步骤二(使用聚合函数去除null,得到最终结果):

select t.deptno,max(decode(row_number,1,sal)) sal1,max(decode(row_number,2,sal)) sal2,max(decode(row_number,3,sal)) sal3 from
 (
 
select emp.*,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
 ) t
where t.rank<=3
group by t.deptno 

结果如下:

10    5000    2450    1300
20    3000    3000    2975
30    2850    1600    1500

 

批量处理一般用在ETL操作, ETL代表提取(extract),转换(transform),装载(load), 是一个数据仓库的词汇!

类似于下面的结构:

for x (select * from...)
loop
    Process data;
    
insert into table values(...);
end loop;

 

一般情况下, 我们处理大笔的数据插入动作, 有2种做法, 第一种就是一笔笔的循环插入

create table t1 as select * from user_tables where 1=0;
create table t2 as select * from user_tables where 1=0;
create table t3 as select table_name from user_tables where 1=0;

 

create or replace procedure Nor_Test
as
begin
     
for x in(select * from user_tables)
     loop
         
insert into t1 values x;
     
end loop;
end;

第2种方法就是批量处理(insert全部字段):

create or replace procedure Bulk_Test1(p_array_size in number)
as
 type array 
is table of user_tables%rowtype;
 l_data array;
 
cursor c is select * from user_tables;
begin
     
open c;
     loop
         
fetch c bulk collect into l_data limit p_array_size;
         
         forall i 
in 1..l_data.count
                
insert into t2 values l_data(i);
         
         
exit when c%notfound;
     
end loop;
end;

insert部分字段:

create or replace procedure Bulk_Test2(p_array_size in number)
as
 l_tablename dbms_sql.Varchar2_Table;
 
cursor c is select table_name from user_tables;
begin
     
open c;
     loop
         
fetch c bulk collect into l_tablename limit p_array_size;
         
         forall i 
in 1..l_tablename.count
                
insert into t3 values (l_tablename(i));
         
         
exit when c%notfound;
     
end loop;
end;

在性能方面批量处理有着很大的优势, p_array_size一般默认都是100

posted on 2012-11-03 21:12  ysu_dx  阅读(155)  评论(0)    收藏  举报