函数是快,因为在服务器上运行只返回结果给你,查询则在前面调用函数.当然要慢些,而且是在前端处理group by.
建议楼主将该查询放到服务器上执行,用游标,然后返回一个记录集到前端程序.直接在前端显示你要的数据就行了.

解决方案 »

  1.   

    to welyngj(平平淡淡) :
       我的这个汉数很简单,就是找一条记录的几个数据项,跟据每个数据项来确定要返回的结果。to dinya2003(OK) :
       请问游标执行的快马?
       我在前段发出去的sql不都是在服务端执行的码?请详细些号码?我没能完全理解你的意思。谢谢啊。
       我是在服务器的sqlplus里做的测试,速度很慢啊,因为需要函数计算。如果是有现成的数据sum,速度非常快。
      

  2.   

    我觉得不合理,用你的函数。
    可以直接用SQL完成的。你用函数的话,首先,它在执行你的函数的时候,就需要几乎扫描你的整个表,
    这样的话,你的记录越多,他坐起来越慢。这个可是迪卡尔集。
    我觉得,说出你的需求,和表结构,可以有办法解决的。
      

  3.   

    你在sum(f_count_task(user_id,to_date('20040101','yyyymmdd'),to_date('20040620','yyyymmdd')) 函数上建一个索引试一试
      

  4.   

    谢谢各位:
       我的需求是这样的:
       统计单位的每个部门的完成任务数,并按任务数排序;而每个部门的任务数是由每个部门的人员完成的任务数加起来的。
       表结构: t_user_task
       myid number(8)         --流水号
       user_id char(8)        --人员id
       depart_id char(4)      --所属部门id
       sales_num number(16,2) --完成销售额
       add_date  date         --加办日期
       undo_date date         --撤办日期
       biz_type  char(1)      --业务类型   
       state   char(1)        --状态     注释:add_date:销售完成后入库日期
             undo_date: 销售退回日期
             biz_type:区别业务类型 可为 1,2,3
       任务数=(销售额折算)乘以(0.3)    
       销售额折算:是根据状态、业务类型、加办日期、撤办日期算出的一个数。
       在统计任务数的时候一定会给出一个时间段。
       因为销售额的折算是一个逻辑处理单元,用一个简单的sql很难实现(起码目前这么认为),所以写了个函数:f_count_task,f_count_task接收员工号、起始日期、终止日期三个参数。
       但感觉运行起来效果不好,速度太慢,我的表数据量有几十万。
       如果不写函数,又不知道怎么写好?
       请大虾帮忙指点啊。
       
       
      

  5.   

    还是函数内部where 语句写的问题。或是索引的合理性问题
      

  6.   

    把你的函数改成视图看看,
    还有增加union的调用!
    减少重复的索引!!!
      

  7.   

    性能慢可能是由很多原因造成的
    建议做以下几件事:
    1.把你函数的具体实现贴出来,让别人给你看看sql是不是可以改进
    2.explain plan看下执行全过程
    3.执行后查看下V$SQL视图
      

  8.   

    我的函数如下,请大家看看哪里可以改进以下,谢谢先!create or replace function f_count_task(in_a varchar2,in_b date,in_c date varchar2)
    return number as
      v1 char(1);
      v2 char(2);
      v3 number(16,2);
      v4 date;
      v5 date;
      v6 date;
      set9 number(2);
    begin   
      execute immediate 'select state,biz_type,saving_num,add_date,withdraw_date,start_date from t_user_task where                     acc='||in_a   into v1,v2,v3,v4,v5,v6;  if v1='1' then    
        if(v2='20')  then
         return round(v3*25/10000,2);
        elsif(v2='21') then
         return round(v3*50/10000,2);
        elsif(v2='23') then
         return round(v3/100,2);
        else
         return round(v3/100,2);
        end if;
      elsif v1='2' then
        if(v4>=in_b) then
           if(v2='20')  then
             return round(v3*25/10000,2);
           elsif(v2='21') then
             return round(v3*50/10000,2);
           elsif(v2='23') then
             return round(v3/100,2);
           else
             return round(v3/100,2);
           end if; 
        else
          return 0;  
        end if;
      elsif v1='3' then
        if((v4>=in_b and v4<=in_c) and (v5>=in_b and v5<=in_c)) then 
           if((v5-v4)>=360) then
              return v3/100;
           else
            select set9 into set9 from t_mgr_rule where area_id=in_d;
             if(v2='20') then
              return round(v3*(v5-v6)*set9*0.25/360000,2);
             elsif(v2='21') then
              return round(v3*(v5-v6)*set9*0.5/360000,2);
             else
              return round(v3*(v5-v6)*set9/360000,2); 
             end if; 
           end if;
        elsif (in_b>v4) then
           if((v5-v4)>=360) then
            return 0;
           else  
            select set9 into set9 from t_mgr_rule where area_id=in_d;
            if(v2='20') then
              return round(v3*(v5-v6)*set9*0.25/360000-v3/100,2); 
            elsif(v2='21') then 
              return round(v3*(v5-v6)*set9*0.5/360000-v3/100,2);
            else
              return round(v3*(v5-v6)*set9/360000-v3/100,2);
            end if;
           end if;
        elsif (v5>in_c) then
           if(v2='20')  then
             return round(v3*25/10000,2);
           elsif(v2='21') then
             return round(v3*50/10000,2);
           elsif(v2='23') then
             return round(v3/100,2);
           else
             return round(v3/100,2);
           end if; 
        end if;  
      end if;exception
      when others then
         return -1;
    end f_user_task; 
      

  9.   

    首先:to_date('20040101','yyyymmdd'),这样的函数在程序里就要转换完成。这样就不要每条记录都去执行一下,这个函数了!
    其次:你用了group by depart_id ,就要在depart_id 字段建立索引,我想,你的速度应该会提高很多!--------希望告诉结果给我!
      

  10.   

    to wupangzi(无本之木):
      请问 “ to_date('20040101','yyyymmdd'),这样的函数在程序里就要转换完成”
      是什么意思啊?怎么在程序转换?
      建索引没问题。
      有结果我会公布的。
      谢谢
      

  11.   

    因为你每次查询都是时间上的固定,不是根据每条记录改变的,所以你根本没必要把这字段带到过程里进去啊!
    我不知道你用的是什么语言,但是一定是可以转换成‘to_date('20040101','yyyymmdd')’这样的格式的。也就是转换成格式date格式就可以了!
      

  12.   

    select set9 into set9 from t_mgr_rule where area_id=in_d;
    你的in_d不需要传入吗?楼上那个人的意思,是让你再传入参数的时候,不要用to_date,在你的函数里面用。
      

  13.   

    select biz_type||state,sum(saving_num) from t_user_task group by biz_type||state;
      

  14.   

    配合decode你可以这样写
    select decode(biz_type||state,'120',round(sum(saving_num)*25/10000,2)) from t_user_task;不过太复杂的逻辑操作………………
      

  15.   

    給个建议
    这种操作无论如何最后是要排序
    在解决sql语句的效率后,应调大 sort_area的值,还有temp表空间的大小