2011-08-10 23 views
0

我在Oracle數據庫中有一個表,其中有一個timestamp列nextTime和一個字符串列destName。還有更多的列,但只有這兩個在這種情況下是相關的。我試圖設計一個查詢,該查詢將在特定時間間隔內返回具有nextTime的不同destName,並且返回的行數應該最大爲一千。當間隔內有超過一千個不同的destName時,我希望查詢返回一千行,而且更多或更少。Oracle SQL選擇不同的查詢以返回特定的行數

我實際上有工作的查詢,但它是太慢:

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; 

如何設計一個更聰明的查詢或如何優化這一exisiting一個任何想法非常讚賞。

+0

執行參數:1和2結合的方式,:1>:2?如果不是,查詢將不會返回任何內容。如果是的話,最好寫'nextTime> =:2和nextTime <:1'來強調參數的順序。 –

+0

@Aleksi:感謝您的評論!是的,:1>:2總是如此。您建議的更改是有意義的,我會應用它。 – joaerl

回答

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:

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

您是不是可以將DISTINCT移動到子查詢中?之後,整個事情可以完成,沒有子查詢。 –

+0

Aleksi,我不確定,並且我試圖將oracle列在ORA-30483問題的'where'子句上。我也嘗試將它包含在「select distinct」部分,但是我不能將rnk限制爲1000個結果。必須有解決方法,但我現在找不到它。 –

+0

'rank'不能用在'WHERE'或'HAVING'中,所以需要子查詢。也許'dense_rank'在這裏會更加合適,雖然它不會跳過某些行列。現在,如果有1000個destName x的實例,則下一個destName將具有等級1001,並且結果只會是一個destName的常量。 –

1

事情我拿起

  1. 你應該離開的執行計劃優化的RDBMS除非你真的知道更好
  2. 沒有必要從最裏面的子查詢

簡單的查詢返回重名與性能稍微不同的語義:

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

無te BETWEEN是包含的,即x BETWEEN y AND z等於y <= x <= z。要排除上限,你必須按照你做的或者減少參數的方式來做:2通過nextTime的單位之一。

+0

謝謝你的回答!建議的查詢絕對是原始查詢的更好的代表。但是,性能並沒有大的提高。可能有相當多的記錄滿足內部查詢的要求(非空和之間)。選擇不同會導致代價高昂嗎?我首先嚐試了沒有嵌套查詢,但問題是,如果前1000行包含相同的destName,我可以在結果集中得到少至1行。 – joaerl