It is possible to get round this problem with a query of the following form:


      select c1 username, c2 fullname, c3 jobtitle, c4 totalcount from (
        select c1, c2, c3, c4, rownum as rowindex from (
          select u.username c1,
                 u.surname c2,
                 u.jobtitle c3,
                 count(*) over() c4
          from   users u,
          where  <<someClause>>
          order by <<sortColIndex>>;
        )) where (rowindex > <<startIndex>>) and (rownum <=
<<resultPageSize>>);

So the inner select gets *all* the matching results plus the total count,
sorted by the desired column; the next select additionally gets the rownum
into rowindex; then the outer select gets just the page of results you want,
retrieving the first <<resultPageSize>> rows from <<startIndex>>. Note that
since the 'order by' is on the inner query, it doesn't suffer from the
ordering problem that Greg mentioned. 

I was warned when I first employed this technique that because the inner
query is selecting *all* matching rows (like Greg's original solution) that
it would be slow, but I found that the full query performs quite well enough
for me. If you have very large result sets then you might start to see
problems, though I haven't tried. 

Al.


> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] 
> Sent: 22 November 2002 00:04
> To: JDJList
> Subject: [jdjlist] Re: Performance Issues (Paging large resultsets)
> 
> 
> 
> Hi,
> 
> Your revised solution is a good idea however it will not work 
> with an ORDER BY clause in the SQL statement. We use Oracle 
> here and originally that was what I wanted to do but I found 
> through much experimentation and consulting the Oracle docs 
> that Oracle will first return the rows up to and/or including 
> what was specified for the ROWNUM setting and THEN it does 
> the ORDER BY!
> 
> So what ends up happening is you find yourself missing some 
> rows that you feel should be there such as when you run the 
> statement without the ROWNUM clause using the ORDER BY and vice-versa.
> 
> You can confirm this behaviour by applying the ROWNUM and 
> ORDER BY clauses independent of each other or in different 
> combinations in the original SQL statement to see what I'm 
> trying to explain here.
> 
> HTH,
> Greg.
> 
> 
> Don Brown <[EMAIL PROTECTED]> on 11/21/2002 04:18:46 PM
> 
> 
> Please respond to "JDJList" <[EMAIL PROTECTED]>
> 
> 
> To:  "JDJList" <[EMAIL PROTECTED]>
> cc:
> 
> 
> 
> Subject:  [jdjlist] Re: Performance Issues (Paging large resultsets)
> 
> 
> 
> 
> This code looks similar to what I used. However, I'll make 
> one point about making it a bit quicker (at least in the 
> earlier pages).
> 
> The code basically returns the entire resultset, and loops 
> through it, adding rows for the page in question to a vector 
> while ignoring the rows before and after those of interest.  
> Okay.  ORACLE provides a pseudo column called ROWNUM which is 
> similar to, yet different from the LIMIT of other DBs like 
> PostgresQL.  SQL to the effect of "SELECT <whatever> FROM 
> <whatever> WHERE <whatever> AND ROWNUM BETWEEN 100 and 120" 
> ****will not work****. It will always return 0 rows.  However 
> it will work if you put only the upper limit on it.  EG: 
> "SELECT <whatever> FROM <whatever> WHERE <whatever> AND 
> ROWNUM <= 120" will work fine.
> 
> In other words, you need to loop and skip all rows before the 
> disired rows, but you don't need to return nor loop through 
> skipping the ones following.
> 
> Similarily, you could change the while loop from:
> -- <snip> ---
> >                 while (rs.next()) {
> >                     nNumRows++;
> >
> >                     if ( (nNumRows >= p_nStartRow) && (nNumRows < 
> > p_nStartRow + p_nMaxRows) ) {
> >                         // Populate our transaction list objects
> >                         TransactionList transactionlist = new 
> > TransactionList(rs.getString(3), rs.getString(5), rs.getInt(6), 
> > rs.getString(7), rs.getString(8),
> > rs.getBigDecimal(9, 2), rs.getBigDecimal(10, 2),
> > rs.getBigDecimal(11, 2), rs.getBigDecimal(12, 4),
> > rs.getBigDecimal(13, 4), rs.getBigDecimal(14, 4),
> > rs.getString(15), rs.getString(17),
> > rs.getString(22),
> > rs.getLong(1), rs.getString(19),
> > rs.getString(23), rs.getString(24),
> > rs.getString(25));
> >                         vData.addElement(transactionlist);
> >                     }
> >                 }
> --- <end snip> ----
> 
> To:
> _-- <snip> ---
> >                 while (rs.next() && (nNumRows < p_nStartRow +
> p_nMaxRows)) {
> --- cut (rest of the loop is the same) -----
> 
> to do the same thing without the pseudo column.
> 
> Someone else had reply about a scrollable resultset which 
> might be more effiecient than this solution, but I have no 
> experience with that.
> 
> Hope this helps,
> Don Brown
> 
> 
> On November 21, 2002 11:56 am, [EMAIL PROTECTED] wrote:
> > Ok guys I'm giving you all a gift.... I had the same problem
> understanding
> > how PetStore does it and after reading much documentation on the 
> > design pattern and various other people's implementation of said 
> > pattern here is my interpretation of the Page-by-Page Iterator 
> > pattern...
> >
> > This is actually still being used in production for a project 
> > developed from three years ago so I know it works... Don't 
> give me a 
> > hard time
> about
> > using a Vector though... If you want to use an ArrayList instead by 
> > all means feel free to change it!
> >
> > Debug is a class I wrote for outputting values while 
> developing/unit 
> > testing so implement your own such as Log4J or whatever. I'ved also
> removed
> > the bulk of the SQL statement as it is somewhat proprietary but I 
> > think
> you
> > will get the drift...
> 
> >  --- <Code is in original reply from [EMAIL PROTECTED]> ---
> 
> ____________________________________________________
> To change your JDJList options, please visit: 
> http://www.sys-con.com/java/list.cfm
> 
> Be respectful! Clean up 
> your posts before replying 
> ____________________________________________________
> 
> 
> 
> 
> **************************************************************
> ****************
> This email message is confidential to the intended recipient 
> and may be legally privileged. It is intended solely for the 
> addressee. Access to this 
> email by anyone else is unauthorized.  Any unauthorised use, 
> dissemination 
> of the information, or copying of this message is prohibited. 
>  If you are 
> not the intended addressee, kindly notify the sender by return e-mail 
> and delete this message.
> **************************************************************
> ****************
> 
> 
> ____________________________________________________
> To change your JDJList options, please visit: 
> http://www.sys-con.com/java/list.cfm
> 
> Be respectful! Clean up 
> your posts before replying 
> ____________________________________________________
> 

____________________________________________________
To change your JDJList options, please visit:
http://www.sys-con.com/java/list.cfm

Be respectful! Clean up your posts before replying
____________________________________________________

Reply via email to