Marcus Leon
Marcus Leon

Reputation: 56699

Oracle rownum on "parent" table

We use Oracle rownum to query two tables t1->t2 which have a one to many relationship:

select * from
(
 select t1.key, t1.a, t2.b
  from t1, t2
 where t1.key=t2.key and <filter conditions> 
 order by t1.a, t2.b
)
where rownum <= 500

This works fine in that it returns the first 500 rows. But what we want is to return the first 500 rows from t1 - and then all the t2 rows that go along with that. What is the best way to do that?

We could remove the rownum sql usage and in Java just read the first 500 unique t1.key values from the resultset (which will be more than 500 total rows in the resultset). But it's not clear if that would be significantly slower.

Upvotes: 0

Views: 218

Answers (2)

sstan
sstan

Reputation: 36513

I think you can accomplish this by using the dense_rank() analytic function:

select * from
(
 select t1.key, t1.a, t2.b,
        dense_rank() over (order by t1.a, t1.key) as rnk 
  from t1, t2
 where t1.key=t2.key 
   and <filter conditions> 
)
where rnk <= 500
order by a, b

For what it's worth, it would be preferable if you get in the habit of using the ANSI join syntax.

EDIT

The above should work fine if t1.a is guaranteed to have unique values in t1. If not, then you may find that my query doesn't quite match the order by logic of your original query. But I don't know if there is anything I can do.

The problem is that because you order by t1.a, t2.b, then, in your original query, there is no guarantee that all the results with the same t1.key value will be grouped together, which makes it unclear how your "first 500 rows" logic is supposed to work based on t1.key.

Upvotes: 4

Gordon Linoff
Gordon Linoff

Reputation: 1270503

There is no concept of "first 500 rows of a table", because tables represent unordered sets. But, if you mean by t1.a, then this might be faster:

select . . .
from (select t.*
      from (select t1.*, 
            from t1
            where exists (select 1 from t2 where t2.key = t1.key and <conditions>)
            order by t1.a
           ) t1
      where rownum <= 500
     ) join
     t2
     on t1.key = t2.key and <filter conditions> 
order by t1.a, t2.b;

Whether this is faster depends on whether the subquery can make use of indexes. Without the filter condition, then an index on t1(a, key) would work. It is unclear if that would work with the unknown conditions.

Upvotes: 0

Related Questions