2011-01-11 84 views
1

無內選擇第一N個不同的行我有類似的結構如下:表1 - >表2的關係是1:米選擇在Oracle

我需要執行類似的查詢到下一個:

select Table1.id from Table1 left outer join Table2 on (Table1.id1 = Table2.id2) where Table2.name like '%a%' and rownum < 11 

即我希望表1中的前10個符合表2中的條件。問題是我必須使用不同的,但在'rownum < 11'之後適用不同的子句,因此結果可能是5個記錄,即使它們的數量超過10

的明顯的解決方法是使用以下命令:

select id from (select Table1.id from Table1 left outer join Table2 on (Table1.id1 = Table2.id2) where Table2.name like '%a%') where rownum < 11 

但我怕這樣的查詢的性能。如果Table1包含大約300k條記錄,並且Table2包含大約700k條記錄,那麼這樣的查詢是不是真的很慢?

是否有另一個查詢,但沒有內部選擇?不幸的是,我想避免使用內部選擇。

+1

難道這樣的查詢真的很慢嗎?如果我知道真的很慢,我可以回答這個問題。 – 2011-01-11 11:42:16

回答

1

對我來說,沒有理由害怕表現。我認爲子選擇是解決問題的最佳方法。如果你不想相信我,看看你的查詢的解釋計劃,你會發現它的表現並不像你想象的那麼糟糕。

3

不幸,我想避免使用內 選擇

隨着具有上TABLE2 WHERE子句,要篩選的選擇爲內連接(即,因爲Table2.name IS NULL <> Table2.name就像'%a%'一樣,只有加入內部時纔會得到結果。另外,沒有基於函數的索引的%a%將導致每次迭代的全表掃描。

但@lweller是完全正確的,要正確執行查詢,您需要使用子查詢。請記住,如果沒有ORDER BY,您不能保證您的頂級X記錄的順序(它可能總是「出現」這些值符合主鍵或什麼,但沒有保證。

WITH TABLE1 AS(SELECT 1 ID FROM DUAL 
       UNION ALL 
       SELECT 2 ID FROM DUAL 
       UNION ALL 
       SELECT 3 ID FROM DUAL 
       UNION ALL 
       SELECT 4 ID FROM DUAL 
       UNION ALL 
       SELECT 5 ID FROM DUAL) , 
    TABLE2 AS(SELECT 1 ID, 'AAA' NAME FROM DUAL 
       UNION ALL 
       SELECT 2 ID, 'ABB' NAME FROM DUAL 
       UNION ALL 
       SELECT 3 ID, 'ACC' NAME FROM DUAL 
       UNION ALL 
       SELECT 4 ID, 'ADD' NAME FROM DUAL 
       UNION ALL 
       SELECT 1 ID, 'BBB' NAME FROM DUAL 
       ) , 
    sortable as(--here is the subquery 
     SELECT 
      Table1.ID , 
      ROW_NUMBER() OVER (ORDER BY Table2.NAME NULLS LAST) ROWOverName , --this wil handle the sort 
      table2.name 
      from 
      Table1 
      LEFT OUTER JOIN --this left join it moot, pull the WHERE table2.name into the join to have it LEFT join as expected 
      Table2 
      on 
      (
       Table1.id = Table2.id 
      ) 
      WHERE 
      Table2.NAME LIKE '%A%') 
    SELECT * 
     FROM sortable 
    WHERE ROWOverName <= 2; 

- 你可以刪除ROW_NUMBER()分析和替換功能最終查詢本身(如您最初所示)

SELECT * 
    FROM sortable 
WHERE 
     ROWNUM <= 2 
ORDER BY sortable.NAME --make sure to put in an order by! 
; 
2

你不需要DISTINCT這裏可言,且有在子查詢中是沒有什麼不好的。

SELECT id 
FROM Table1 
WHERE id IN 
     (
     SELECT id 
     FROM Table2 
     WHERE name LIKE '%a%' 
     ) 
     AND rownum < 11 

請注意,訂單不能保證。爲了保證秩序,你必須使用一個嵌套查詢:

SELECT id 
FROM (
     SELECT id 
     FROM Table1 
     WHERE id IN 
       (
       SELECT id 
       FROM Table2 
       WHERE name LIKE '%a%' 
       ) 
     ORDER BY 
       id -- or whatever else 
     ) 
WHERE rownum < 11 

有沒有辦法做到這一點沒有嵌套查詢(或CTE)。