Oracle SQL选择不同的查询以返回特定的行数

时间:2011-08-10 08:32:38

标签: sql oracle query-optimization distinct rownum

我在Oracle数据库中有一个表,其时间戳列为nextTime,字符串列为destName。还有更多列,但在这种情况下只有这两个列相关。我正在尝试设计一个查询,它将在特定的时间间隔内返回具有nextTime的不同destName,并且返回的行数应该最多为1000。当区间内有超过一千个不同的destName时,我希望查询返回一千行,而不是更多或更少。

我实际上有一个正在运行的查询,但它太慢了:

select destName 
from (select /*+ index(tblDestNames tbldestnames_destname)*/ distinct destName
from (select /*+ index(tblDestNames tbldestnames_nextTime)*/ destName
from tblDestNames 
where nextTime < :1 and nextTime >= :2 and destName is not null)) 
where rownum <= 1000; 

非常感谢任何关于如何设计更智能的查询或如何优化现有查询的想法。

2 个答案:

答案 0 :(得分:6)

我不确定是否有理由不简化查询:

select destName 
from (
    select distinct destName
    from tblDestNames 
    where nextTime < :1 and nextTime >= :2 and destName is not null
    )
where rownum <= 1000; 

但是,这不会解决您的性能问题。问题是:

where rownum <= 1000

将rownum替换为'rank'和'over',你会得到类似的东西:

select distinct destName
from (
    select
       destName
    from
       (select destName, rank()
        over (order by destName desc ) rnk
        from tblDestNames
        where nextTime < :1 and nextTime >= :2 and destName is not null) 
    where rnk <= 1000;
    )

奖励是,在“结束”时,您选择将显示的结果的顺序和不会显示的结果。

编辑:实际上它可以进一步简化为:

select
   distinct destName
from
   (select destName, rank()
    over (order by destName desc ) rnk
    from tblDestNames
    where nextTime < :1 and nextTime >= :2 and destName is not null) 
where rnk <= 1000;

答案 1 :(得分:1)

我拿起的东西

  1. 您应该将执行计划优化留给RDBMS,除非您真的了解更多
  2. 无需从最里面的子查询中返回重复的名称
  3. 使用略有不同的语义进行更简单的查询:

    SELECT destName
    FROM (SELECT DISTINCT destName
          FROM tblDestNames
          WHERE destName IS NOT NULL 
            AND nextTime NOT BETWEEN :1 and :2)
    WHERE rownum <= 1000;
    

    请注意,BETWEEN具有包容性,即x BETWEEN y AND z等于y <= x <= z。要排除上限,你要么必须像你做的那样去做,要么减少参数:2 by unit nextTime是什么。