2014-09-21 76 views
3

我已經編寫了一個查詢,該查詢的總結果集爲n%。我不確定這是否是一種有效的查詢方式。Oracle - 限制Row_number()的百分比

以下是我的查詢(其修改的一個理解),從總的結果集給出了20%:

SELECT * 
FROM (
    WITH RS AS (
      SELECT ID 
       ,ROW_NUMBER() OVER (
        ORDER BY ID 
        ) r_num 
       ,count(1) OVER() AS n_rows 
      FROM TAB1 
      LEFT OUTER JOIN TAB2 ON TAB1.ID = TAB2.ID 
      INNER JOIN TAB4 ON TAB4.ID = TAB4.ID 
      INNER JOIN TAB3 ON TAB3.ID = TAB4.ID 
      WHERE TAB2.ID_ IS NULL 
       AND TAB3.C_ID = 'JP' 
      ) 
    SELECT * 
    FROM RS 
    WHERE r_num <= round(n_rows * 0.2) 
    ORDER BY ID 
    ) 

你有什麼建議從結果,可以採取第一/最後一個/隨機N%以有效的方式設置?

+0

在Oracle中,你也可以使用'sample(20)'子句來獲得select語句的20%(隨機)行。 – 2014-09-21 06:54:10

+0

它不會幫助OP,因爲他正在尋找一個有序的行。我在12c和之前的版本中是'NTILE'。在12c中,我們現在也有使用百分比的新「行限制子句」。 – 2014-09-21 07:57:17

回答

3

既然你是在11g(從標籤看來),我建議NTILE分析功能。您可以在文檔中閱讀有關NTILE的更多信息。 NTILE會將有序數據集分成若干個桶。在你的情況,例如,前10%的行會是這樣的:

NTILE (10) OVER (ORDER BY id)

的查詢可以被改寫爲:

WITH RS AS (
      SELECT ID 
       ,NTILE (10) OVER (ORDER BY id) r_num 
      FROM TAB1 
      LEFT OUTER JOIN TAB2 ON TAB1.ID = TAB2.ID 
      INNER JOIN TAB4 ON TAB4.ID = TAB4.ID 
      INNER JOIN TAB3 ON TAB3.ID = TAB4.ID 
      WHERE TAB2.ID_ IS NULL 
       AND TAB3.C_ID = 'JP' 
      ) 
SELECT id 
    FROM rs 
    WHERE r_num = 10 
ORDER BY id 

注:由於您沒有提供一個測試用例,我沒有你的表格和數據來重新創建測試用例。

這是有關以前12c,現在12c你有新的ROW LIMITING CLAUSE,你只是需要將其添加到子句:

FETCH FIRST 10 PERCENT ROWS ONLY

例如:

SELECT col 
FROM table 
ORDER BY col 
FETCH FIRST 10 PERCENT ROWS ONLY; 

它給優於舊的ROWNUM,這在預期有序結果集時一直是個問題。使用12c中的新行限制子句,在上例中,您將始終獲得ORDERED結果集。你可以在這裏看到更多的例子ROW LIMITING clause

+0

感謝@Sylvain修復URL – 2014-09-21 14:54:17

+1

NTILE是一個魅力!非常感謝.. – Logan 2014-09-22 04:08:41

+0

是的,是的。沒有多少人知道它:-)現在你也知道了。 – 2014-09-22 04:40:32