关注一下。
不过在SQLSERVER里最后求95%概率不需要分两步,一步就可以了。
我觉得也不需要做循环,游标或循环的效率不高。
“表tmp 中的记录按时间排序,然后两个小时的记录作为一组,
求得time的中间值(该组的开始时间再加一个小时),”这一部是要生成一个结果集。生成的结果集只要一个SQL语句应该就可以得到最后的结果集了。不知道你分组的结果集的格式。要不我写给你看了:)以上的看法应该在ORACLE中也是一样,应该不需要用循环的。

解决方案 »

  1.   

    1、两个SQL语句是可以合成一个,但我觉得SQLSERVER对它的处理是一样的。
    2、您可能还没有明白我的意思吧,您再仔细看一下我的需求谢谢关注。
      

  2.   

    to  icevi(按钮工厂) 
     1、两个SQL语句是可以合成一个,但我觉得SQLSERVER对它的处理是一样的。
    2、您可能还没有明白我的意思吧,您再仔细看一下我的需求谢谢关注。
      

  3.   

    icevi(按钮工厂) :
    请解释一下
    什么情况下ORACLE使用的临时表?
    什么情况下临时表是可以提高性能的?
      

  4.   

    我并不太了解ORACLE,但是我想这方面应该与SQL SERVER类似的。SQL SERVER里,使用临时表,这些表会存放到 tempdb这个数据库里去。会产生些磁盘I/O操作。 而磁盘I/O操作对性能影响是很大的。如果不用临时表,大部分运算是在内存中进行,当然也有可能会在需要做分组排序等操作时,也使用tempdb来做这些处理,但相比用临时表来说,还是少了很多磁盘I/O的操作,而且有很多查询是不需要使用tempdb的,性能更不一样了。在SQL SERVER 2000里还可以用表变量来代替使用临时表,表变量也可能象操作表一样去操作它,但它不会去写磁盘,完全在内存中进行,所以速度会比用临时表快很多。但是如果数据量非常非常大,用表变量会占用大量内存,会造成整体性能受影响,这时候可能用临时表会更好一点。 我觉得用ORACLE也类似,好象一般在用ORACLE时会为临时表建一个单独的表空间,临时表的存储就在这个表空间上进行,其实与tempdb类似。所以ORACLE里用临时表也是一样会增加磁盘I/O操作,对性能的影响应该也是类似。所以视具体情况选择是用一条SQL语句来做 ,或是用表变量来做,或是用临时表来做,几种方法各有优缺点,不同的服务器配置下可能效果也不一样。所以要具体情况具体分析。你测出来的速度并不能表示说哪种DBMS更好或更差,服务器的一些配置对性能都会有影响,这样比较并不是太能说明问题。我只是想说明我的看法,你可以试下对oracle的方法做些优化,用不同的方法来尝试一下,可能会找到更快的解决办法的。
      

  5.   

    谢谢icevi(按钮工厂)
    您说的这段话我比较认同可惜我的问题还没怎么解决
    您号召他们关注一下吗!
      

  6.   

    我一定抽出时间研究研究你这个问题。
    我相信ORACLE在性能上要比SQL Server 好。
    ^=^
      

  7.   

    glmcglmc(joe) :是啊,我可是ORACLE菜鸟一个,本来是来听讲的:)怎么没有人其他人关注这个问题呢?
      

  8.   

    chenbf_sz(大象):
    我也相信ORACLE
    牛,
    并且我下决心与她为伴,靠她吃饭
      

  9.   

    不需要循环.1. 建立一个临时表,作为驱动表
    create table time_period
    ( start_time date,
      end_time   date);
    数据示例如下:
    start_time          end_time
    -----------------   -------------
    02-12-12 12:00:00   02-12-12 13:59:59
    02-12-12 14:00:00   02-12-12 15:59:59
    02-12-12 16:00:00   02-12-12 17:59:592.用一句SQL能>95的返回结果集:
    select y.start_time + 1, value
      from tmp x, time_period y
     where x.time between x.start_time and x.end_time
       and percent_rank() over (partition by y.start_time, order by value desc) < 0.05;
      

  10.   

    to improve performance, maybe it's better to do like below
    1. create temp table
    create table time_period
    (start_time date,
     end_time   date,
     rowcount   number(10),
     per95_pos  number(10));2. init time_period
      start_time        end_time
      ----------------- -----------------
      11-04-02 12:00:00 11-04-02 13:59:59
      11-04-02 14:00:00 11-04-02 15:59:59
      11-04-02 16:00:00 11-04-02 17:59:59
      11-04-02 18:00:00 11-04-02 19:59:59
      
    3. update time_period with rowcount, per95_pos
    update time_period x
       set rowcount = (select count(*) from tmp
                        where time between x.start_time and x.end_time);
    update time_period x
       set per95_pos = trunc(rowcount * .05);4. get recordset you want:
    select y.start_time + 1, value
      from tmp x, time_period y
     where x.time between x.start_time and x.end_time
       and trunc(percent_rank() over (partition by y.start_time, order by value desc) * rowcount) =  per95_pos;
      

  11.   

    KingSunSha(弱水三千) :
    您这样做的方法会比我用的方法性能好吗?
    若是,
    请解释一下原因好吗?
      

  12.   

    my final suggestion, tested on oracle 8.171. create temp table
    create table time_period
    (start_time date,
     end_time   date);2. init time_period
      start_time        end_time
      ----------------- -----------------
      11-04-02 12:00:00 11-04-02 13:59:59
      11-04-02 14:00:00 11-04-02 15:59:59
      11-04-02 16:00:00 11-04-02 17:59:59
      11-04-02 18:00:00 11-04-02 19:59:59
      
    3. get all records which belongs top 5% and save to a temp table
    create table tmp2 as
    select *
      from (select y.start_time + 1 cur_time, value,
                   percent_rank() over (partition by y.start_time order by value desc) pr
              from tmp x, time_period y
             where x.time between y.start_time and y.end_time) x
     where pr < .05;4. get final recordset:
    select cur_time, value 
      from tmp2 x
     where pr = (select max(pr)
                   from tmp2
      where cur_time = x.cur_time);comments:
    your performance problem looks most likely because of 2 reasons:
    1. looping many times based on time periods caused many times of table read. it's always better to reduce table read times, especially on large tables. obviously, in my solution, system will only read from table 'tmp' once, I believe it's much better solution than your original one.
    2. 'order by' activities will slow down query speed seriously, especially on large tables. because 'order by' only works on the query result instead of base tables. that means each 'order by' activity will force system to get all rows from result set before performing. so it's better to aviod using 'order by' if possible. so in my solution, I use 'order by' clause only once.I believe there must be other solutions better than mine. but I don't have enough data volumn to run a full test on performance. You are more than welcome to give out more detail information about your situation, like how many rows in main table, how many for each time period, indexes and etc, then  we can discuss it deeply further.I'm sorry to write it in English, there are some problem with my NT4 and Chinese IME.Good Luck!