Reputation: 1371
I have written a query that gives n% from the total result set. I am not sure whether it is an efficient way to query.
Following is my query (its a modified one for understanding) which gives 20% from the total result set:
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
)
Do you have any suggestions to take first/last/random n% from the result set in an efficient way ?
Upvotes: 3
Views: 1534
Reputation: 49092
Since you are on 11g
(as it seems from the tag), I would suggest NTILE
analytic function. You can read more about NTILE in the documentation. NTILE would divide the ordered data set into a number of buckets. In your case, for example, the top 10% rows would be something like :
NTILE (10) OVER (ORDER BY id)
The query could be rewritten as :
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
Note : Since you did not provide a test case, I don't have your tables and data to recreate a test case.
That was about prior 12c
, now in 12c
you have the new ROW LIMITING CLAUSE
where you need to just add this to the clause :
FETCH FIRST 10 PERCENT ROWS ONLY
For example :
SELECT col
FROM table
ORDER BY col
FETCH FIRST 10 PERCENT ROWS ONLY;
It gives the advantage over the old ROWNUM
which has had always been an issue when an ordered result set is expected. With the new row limiting clause in 12c, in my example above, you will always get an ORDERED
result set. You can look more examples here ROW LIMITING clause
Upvotes: 3