实际应用中我们可以通过sum()统计出组中的总计或者是累加值,具体示例如下:

1.创建演示表

Oracle]高效的SQL语句之分析函数create table emp
Oracle]高效的SQL语句之分析函数
as
Oracle]高效的SQL语句之分析函数
select * from scott.emp;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
alter table emp
Oracle]高效的SQL语句之分析函数
add constraint emp_pk
Oracle]高效的SQL语句之分析函数
primary key(empno);
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
create table dept
Oracle]高效的SQL语句之分析函数
as
Oracle]高效的SQL语句之分析函数
select * from scott.dept;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
alter table dept
Oracle]高效的SQL语句之分析函数
add constraint dept_pk
Oracle]高效的SQL语句之分析函数
primary key(deptno);
Oracle]高效的SQL语句之分析函数


2. sum()语句如下:

Oracle]高效的SQL语句之分析函数select deptno,
Oracle]高效的SQL语句之分析函数       ename,
Oracle]高效的SQL语句之分析函数       sal,
Oracle]高效的SQL语句之分析函数  
--按照部门薪水累加(order by改变了分析函数的作用,只工作在当前行和前一行,而不是所有行)
Oracle]高效的SQL语句之分析函数
       sum(sal) over (partition by deptno order by sal) CumDeptTot,  
Oracle]高效的SQL语句之分析函数       
sum(sal) over (partition by deptno) SalByDept,  --统计一个部门的薪水
Oracle]高效的SQL语句之分析函数
       sum(sal) over (order by deptno,sal) CumTot,  --所有雇员的薪水一行一行的累加
Oracle]高效的SQL语句之分析函数
       sum(sal) over () TotSal  --统计总薪水
Oracle]高效的SQL语句之分析函数
  from emp
Oracle]高效的SQL语句之分析函数 
order by deptno, sal
Oracle]高效的SQL语句之分析函数

3. 结果如下:

Oracle]高效的SQL语句之分析函数10    MILLER    1300.00    1300    8750    1300    29025
Oracle]高效的SQL语句之分析函数10    CLARK    2450.00    3750    8750    3750    29025
Oracle]高效的SQL语句之分析函数10    KING    5000.00    8750    8750    8750    29025
Oracle]高效的SQL语句之分析函数20    SMITH    800.00    800    10875    9550    29025
Oracle]高效的SQL语句之分析函数20    ADAMS    1100.00    1900    10875    10650    29025
Oracle]高效的SQL语句之分析函数20    JONES    2975.00    4875    10875    13625    29025
Oracle]高效的SQL语句之分析函数20    SCOTT    3000.00    10875    10875    19625    29025
Oracle]高效的SQL语句之分析函数20    FORD    3000.00    10875    10875    19625    29025
Oracle]高效的SQL语句之分析函数30    JAMES    950.00    950    9400    20575    29025
Oracle]高效的SQL语句之分析函数30    WARD    1250.00    3450    9400    23075    29025
Oracle]高效的SQL语句之分析函数30    MARTIN    1250.00    3450    9400    23075    29025
Oracle]高效的SQL语句之分析函数30    TURNER    1500.00    4950    9400    24575    29025
Oracle]高效的SQL语句之分析函数30    ALLEN    1600.00    6550    9400    26175    29025
Oracle]高效的SQL语句之分析函数30    BLAKE    2850.00    9400    9400    29025    29025

 

如果我们按照示例想得到每个部门薪水值最高的雇员的纪录,可以有四种方法实现:

先创建示例表

Oracle]高效的SQL语句之分析函数create table emp
Oracle]高效的SQL语句之分析函数
as
Oracle]高效的SQL语句之分析函数
select * from scott.emp;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
alter table emp
Oracle]高效的SQL语句之分析函数
add constraint emp_pk
Oracle]高效的SQL语句之分析函数
primary key(empno);
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
create table dept
Oracle]高效的SQL语句之分析函数
as
Oracle]高效的SQL语句之分析函数
select * from scott.dept;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
alter table dept
Oracle]高效的SQL语句之分析函数
add constraint dept_pk
Oracle]高效的SQL语句之分析函数
primary key(deptno);


方法1.emp中的每一行都会进行max比较,费时

Oracle]高效的SQL语句之分析函数select * from emp emp1 where emp1.sal=(select max(emp2.sal) from emp emp2 where emp2.deptno=emp1.deptno)


方法2.先子查询查找出max sal,然后与emp表相关联,如果逻辑复杂会产生较多代码

   select * from emp emp1,(select deptno,max(sal) maxsal from emp emp2 group by emp2.deptno) emp3 where emp1.deptno=emp3.deptno and emp1.sal=emp3.maxsal


方法3.使用max分析函数

Oracle]高效的SQL语句之分析函数select deptno,maxsal,empno from(
Oracle]高效的SQL语句之分析函数 
select max(sal) over (partition by deptno) maxsal,emp.* from emp) emp2
Oracle]高效的SQL语句之分析函数 
where emp2.sal=emp2.maxsal


方法4.使用dense_rank分析函数,如果一个部门可能存在多笔最大薪水,就不能使用row_number()分析函数

Oracle]高效的SQL语句之分析函数select deptno,sal,empno from
Oracle]高效的SQL语句之分析函数 
select emp.*,DENSE_RANK() over (partition by deptno order by sal desc) rownumber from emp) emp2
Oracle]高效的SQL语句之分析函数 
where rownumber=1 

结果如下:

Oracle]高效的SQL语句之分析函数10    5000.00    7839
Oracle]高效的SQL语句之分析函数
20    3000.00    7788
Oracle]高效的SQL语句之分析函数
20    3000.00    7902
Oracle]高效的SQL语句之分析函数
30    2850.00    7698

 

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

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

先创建示例表

Oracle]高效的SQL语句之分析函数create table emp
Oracle]高效的SQL语句之分析函数
as
Oracle]高效的SQL语句之分析函数
select * from scott.emp;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
alter table emp
Oracle]高效的SQL语句之分析函数
add constraint emp_pk
Oracle]高效的SQL语句之分析函数
primary key(empno);
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
create table dept
Oracle]高效的SQL语句之分析函数
as
Oracle]高效的SQL语句之分析函数
select * from scott.dept;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
alter table dept
Oracle]高效的SQL语句之分析函数
add constraint dept_pk
Oracle]高效的SQL语句之分析函数
primary key(deptno);
Oracle]高效的SQL语句之分析函数

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

Oracle]高效的SQL语句之分析函数 select emp.deptno,emp.sal,emp.empno,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
Oracle]高效的SQL语句之分析函数
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
Oracle]高效的SQL语句之分析函数
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2

结果如下:

Oracle]高效的SQL语句之分析函数10    5000.00    7839    1    1    1
Oracle]高效的SQL语句之分析函数
10    2450.00    7782    2    2    2
Oracle]高效的SQL语句之分析函数
10    1300.00    7934    3    3    3
Oracle]高效的SQL语句之分析函数
20    3000.00    7788    1    1    1
Oracle]高效的SQL语句之分析函数
20    3000.00    7902    2    1    1
Oracle]高效的SQL语句之分析函数
20    2975.00    7566    3    3    2
Oracle]高效的SQL语句之分析函数
20    1100.00    7876    4    4    3
Oracle]高效的SQL语句之分析函数
20    800.00    7369    5    5    4
Oracle]高效的SQL语句之分析函数
30    2850.00    7698    1    1    1
Oracle]高效的SQL语句之分析函数
30    1600.00    7499    2    2    2

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

Oracle]高效的SQL语句之分析函数select t.deptno,t.rank,t.sal from
Oracle]高效的SQL语句之分析函数 (
Oracle]高效的SQL语句之分析函数 
select emp.*,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
Oracle]高效的SQL语句之分析函数
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
Oracle]高效的SQL语句之分析函数
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
Oracle]高效的SQL语句之分析函数
 ) t
Oracle]高效的SQL语句之分析函数
where t.rank<=3

结果如下:

Oracle]高效的SQL语句之分析函数10    1    5000.00
Oracle]高效的SQL语句之分析函数
10    2    2450.00
Oracle]高效的SQL语句之分析函数
10    3    1300.00
Oracle]高效的SQL语句之分析函数
20    1    3000.00
Oracle]高效的SQL语句之分析函数
20    1    3000.00
Oracle]高效的SQL语句之分析函数
20    3    2975.00
Oracle]高效的SQL语句之分析函数
30    1    2850.00
Oracle]高效的SQL语句之分析函数
30    2    1600.00
Oracle]高效的SQL语句之分析函数
30    3    1500.00

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

Oracle]高效的SQL语句之分析函数select t.deptno,decode(row_number,1,sal) sal1,decode(row_number,2,sal) sal2,decode(row_number,3,sal) sal3 from
Oracle]高效的SQL语句之分析函数 (
Oracle]高效的SQL语句之分析函数 
select emp.*,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
Oracle]高效的SQL语句之分析函数
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
Oracle]高效的SQL语句之分析函数
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
Oracle]高效的SQL语句之分析函数
 ) t
Oracle]高效的SQL语句之分析函数
where t.rank<=3
Oracle]高效的SQL语句之分析函数

结果如下:

Oracle]高效的SQL语句之分析函数10    5000        
Oracle]高效的SQL语句之分析函数
10                  2450    
Oracle]高效的SQL语句之分析函数
10                             1300
Oracle]高效的SQL语句之分析函数
20    3000        
Oracle]高效的SQL语句之分析函数
20                  3000    
Oracle]高效的SQL语句之分析函数
20                              2975
Oracle]高效的SQL语句之分析函数
30    2850        
Oracle]高效的SQL语句之分析函数
30                 1600    
Oracle]高效的SQL语句之分析函数
30                             1500

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

Oracle]高效的SQL语句之分析函数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
Oracle]高效的SQL语句之分析函数 (
Oracle]高效的SQL语句之分析函数 
select emp.*,row_number() over (partition by deptno order by sal desc) row_number,  --1,2,3
Oracle]高效的SQL语句之分析函数
  rank() over (partition by deptno order by sal desc) rank, --1,1,3
Oracle]高效的SQL语句之分析函数
  dense_rank() over (partition by deptno order by sal desc) dense_rank from emp --1,1,2
Oracle]高效的SQL语句之分析函数
 ) t
Oracle]高效的SQL语句之分析函数
where t.rank<=3
Oracle]高效的SQL语句之分析函数
group by t.deptno 

结果如下:

Oracle]高效的SQL语句之分析函数10    5000    2450    1300
Oracle]高效的SQL语句之分析函数
20    3000    3000    2975
Oracle]高效的SQL语句之分析函数
30    2850    1600    1500

 

有时候报表上面需要显示该笔操作的上一步骤或者下一步骤的详细信息,这个时候可以按照下面的做法:

先创建示例表:

Oracle]高效的SQL语句之分析函数-- Create table
Oracle]高效的SQL语句之分析函数
create table LEAD_TABLE
Oracle]高效的SQL语句之分析函数(
Oracle]高效的SQL语句之分析函数  CASEID     
VARCHAR2(10),
Oracle]高效的SQL语句之分析函数  STEPID     
VARCHAR2(10),
Oracle]高效的SQL语句之分析函数  ACTIONDATE DATE
Oracle]高效的SQL语句之分析函数)
Oracle]高效的SQL语句之分析函数tablespace COLM_DATA
Oracle]高效的SQL语句之分析函数  pctfree 
10
Oracle]高效的SQL语句之分析函数  initrans 
1
Oracle]高效的SQL语句之分析函数  maxtrans 
255
Oracle]高效的SQL语句之分析函数  storage
Oracle]高效的SQL语句之分析函数  (
Oracle]高效的SQL语句之分析函数    initial 64K
Oracle]高效的SQL语句之分析函数    minextents 
1
Oracle]高效的SQL语句之分析函数    maxextents unlimited
Oracle]高效的SQL语句之分析函数  );
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step1',to_date('20070101','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step2',to_date('20070102','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step3',to_date('20070103','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step4',to_date('20070104','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step5',to_date('20070105','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step4',to_date('20070106','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step6',to_date('20070101','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case1','Step1',to_date('20070201','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case2','Step2',to_date('20070202','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
insert into LEAD_TABLE values('Case2','Step3',to_date('20070203','yyyy-mm-dd'));
Oracle]高效的SQL语句之分析函数
commit;
Oracle]高效的SQL语句之分析函数

 

每一条记录都能连接到上/下一行的内容

Oracle]高效的SQL语句之分析函数select caseid,stepid,actiondate,lead(stepid) over (partition by caseid order by actiondate) nextstepid,
Oracle]高效的SQL语句之分析函数lead(actiondate) 
over (partition by caseid order by actiondate) nextactiondate,
Oracle]高效的SQL语句之分析函数lag(stepid) 
over (partition by caseid order by actiondate) prestepid,
Oracle]高效的SQL语句之分析函数lag(actiondate) 
over (partition by caseid order by actiondate) preactiondate
Oracle]高效的SQL语句之分析函数
from lead_table

结果如下:

Oracle]高效的SQL语句之分析函数Case1    Step1    2007-1-1    Step2    2007-1-2        
Oracle]高效的SQL语句之分析函数Case1    Step2    
2007-1-2    Step3    2007-1-3    Step1    2007-1-1
Oracle]高效的SQL语句之分析函数Case1    Step3    
2007-1-3    Step4    2007-1-4    Step2    2007-1-2
Oracle]高效的SQL语句之分析函数Case1    Step4    
2007-1-4    Step5    2007-1-5    Step3    2007-1-3
Oracle]高效的SQL语句之分析函数Case1    Step5    
2007-1-5    Step4    2007-1-6    Step4    2007-1-4
Oracle]高效的SQL语句之分析函数Case1    Step4    
2007-1-6    Step6    2007-1-7    Step5    2007-1-5
Oracle]高效的SQL语句之分析函数Case1    Step6    
2007-1-7                                       Step4    2007-1-6
Oracle]高效的SQL语句之分析函数Case2    Step1    
2007-2-1    Step2    2007-2-2        
Oracle]高效的SQL语句之分析函数Case2    Step2    
2007-2-2    Step3    2007-2-3    Step1    2007-2-1
Oracle]高效的SQL语句之分析函数Case2    Step3    
2007-2-3                                       Step2    2007-2-2

 

还可以进一步统计一下两者的相差天数

Oracle]高效的SQL语句之分析函数select caseid,stepid,actiondate,nextactiondate,nextactiondate-actiondate datebetween from (
Oracle]高效的SQL语句之分析函数
select caseid,stepid,actiondate,lead(stepid) over (partition by caseid order by actiondate) nextstepid,
Oracle]高效的SQL语句之分析函数lead(actiondate) 
over (partition by caseid order by actiondate) nextactiondate,
Oracle]高效的SQL语句之分析函数lag(stepid) 
over (partition by caseid order by actiondate) prestepid,
Oracle]高效的SQL语句之分析函数lag(actiondate) 
over (partition by caseid order by actiondate) preactiondate
Oracle]高效的SQL语句之分析函数
from lead_table) 

结果如下:

Oracle]高效的SQL语句之分析函数Case1    Step1    2007-1-1    2007-1-2    1
Oracle]高效的SQL语句之分析函数Case1    Step2    
2007-1-2    2007-1-3    1
Oracle]高效的SQL语句之分析函数Case1    Step3    
2007-1-3    2007-1-4    1
Oracle]高效的SQL语句之分析函数Case1    Step4    
2007-1-4    2007-1-5    1
Oracle]高效的SQL语句之分析函数Case1    Step5    
2007-1-5    2007-1-6    1
Oracle]高效的SQL语句之分析函数Case1    Step4    
2007-1-6    2007-1-7    1
Oracle]高效的SQL语句之分析函数Case1    Step6    
2007-1-7        
Oracle]高效的SQL语句之分析函数Case2    Step1    
2007-2-1    2007-2-2    1
Oracle]高效的SQL语句之分析函数Case2    Step2    
2007-2-2    2007-2-3    1
Oracle]高效的SQL语句之分析函数Case2    Step3    
2007-2-3        

 

Oracle支持通过ref游标在调用存储过程后返回结果集, 使用游标在内存消耗以及时间上都要大大的优于返回数组变量的做法!

示例如下:数据库方面,建立一个Package

Oracle]高效的SQL语句之分析函数create or replace package ref_cur_demo is
Oracle]高效的SQL语句之分析函数 type rc 
is ref cursor;
Oracle]高效的SQL语句之分析函数 
procedure ref_cursor(p_owner in varchar2,p_cursor in out rc);
Oracle]高效的SQL语句之分析函数
end ref_cur_demo;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数
create or replace package body ref_cur_demo is
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数 
procedure ref_cursor(p_owner in varchar2,p_cursor in out rc)
Oracle]高效的SQL语句之分析函数 
is 
Oracle]高效的SQL语句之分析函数 
begin
Oracle]高效的SQL语句之分析函数      
open p_cursor for select object_name,object_type from all_objects where owner = p_owner and rownum<3
Oracle]高效的SQL语句之分析函数 
end;
Oracle]高效的SQL语句之分析函数  
Oracle]高效的SQL语句之分析函数
end ref_cur_demo;
Oracle]高效的SQL语句之分析函数

程序方面使用C#建立一个小型应用程序,主要代码如下:

Oracle]高效的SQL语句之分析函数            Oracle.DataAccess.Client.OracleConnection oracleConnection1=new OracleConnection("data source=precolm2;user id=colmtest;password=colmtest");
Oracle]高效的SQL语句之分析函数            oracleConnection1.Open();
Oracle]高效的SQL语句之分析函数            
string strSQL = @"ref_cur_demo.ref_cursor";
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数            Oracle.DataAccess.Client.OracleDataAdapter da 
= new Oracle.DataAccess.Client.OracleDataAdapter();
Oracle]高效的SQL语句之分析函数            Oracle.DataAccess.Client.OracleCommand cmd 
= new Oracle.DataAccess.Client.OracleCommand(strSQL,oracleConnection1);
Oracle]高效的SQL语句之分析函数            cmd.CommandType 
= CommandType.StoredProcedure;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数            Oracle.DataAccess.Client.OracleParameter pram 
= new Oracle.DataAccess.Client.OracleParameter("p_owner",Oracle.DataAccess.Client.OracleDbType.Varchar2);
Oracle]高效的SQL语句之分析函数            pram.Value 
= "COLMTEST";
Oracle]高效的SQL语句之分析函数            cmd.Parameters.Add(pram);
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数            Oracle.DataAccess.Client.OracleParameter pram1 
= new Oracle.DataAccess.Client.OracleParameter("p_cursor",Oracle.DataAccess.Client.OracleDbType.RefCursor);
Oracle]高效的SQL语句之分析函数            pram1.Direction 
= ParameterDirection.Output;
Oracle]高效的SQL语句之分析函数            cmd.Parameters.Add(pram1);
Oracle]高效的SQL语句之分析函数            
Oracle]高效的SQL语句之分析函数            da.SelectCommand 
= cmd;
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数            DataSet ds 
= new DataSet();
Oracle]高效的SQL语句之分析函数
Oracle]高效的SQL语句之分析函数            da.Fill(ds);
Oracle]高效的SQL语句之分析函数                
Oracle]高效的SQL语句之分析函数            
this.dataGrid1.DataSource=ds.Tables[0].DefaultView;

 

 

相关文章: