tags:

views:

242

answers:

3

The query remains constant, but the offset varies.

SELECT NAME from tbl WHERE alphabet_index='A' limit 880,1;
SELECT NAME from tbl WHERE alphabet_index='A' limit 1760,1;
SELECT NAME from tbl WHERE alphabet_index='A' limit 2640,1;
....
SELECT NAME from tbl WHERE alphabet_index='A' limit 34320,1;

Is there a better way to do this without having to run N queries with different offsets?

Update: I am trying to build name ranges as an index for a drill down. So if an alphabet_index has 50000 records and I would like to display 40 ranges, I am calculating offset = total/rangeCount. My desired end result would be

AA...-AA...
AA...-AB...
AB...-AC...
AC...-AC...
AD...-AF...
...
...
AW...-AZ...
A: 

Like this:

with x as(
select row_number() over (order by SomeColumn) Id, *
from MyTable
)
select *
from MyTable
where Id in (1, 3, 5)

Update: my bad, this works only in MSSQL

_simon_
Is that true in MySql?
astander
+1  A: 

In order to build ranges for a drilldown, I would actually fetch that one field, and fetch all records. Often, the latency of making multiple queries is larger than the time it takes to fetch that extra data. It would also solve the other problem, that multiple queries may be based on different versions of the data (unless you are using transactions).

In other words, use the very low tech solution. If you want to optimize further, use stored procedures, to make that same query, but so that the stored procedure is returning every Nth record instead of having your code filter them out:

http://dev.mysql.com/doc/refman/5.0/en/stored-routines.html

Lars D
+4  A: 

You can do a varying offset query in a single query like this

select NAME from 
   (select @row:=@row+1 as row, t.NAME from 
    tbl t, (select @row := 0) y 
    where alphabet_index='A' order by alphabet_index) z 
where row % 880 = 1;

This will add a unique integer id to each row via the @row variable. Then it will select a row every other 880 via the modulo operator and that variable. An order by clause is required to get repeatable behavior, else the result would be effectively random.

Vinko Vrsalovic
Your solution almost works perfectly. How do I determine the end of one range and the start of the next? Your query generates the start point of all the ranges. The end point of the range would be (row%880)=0. Thanks in advance.
Shoan
How about `where row % 880 = 1 or row % 880 = 0`?
Vinko Vrsalovic
Do I need "order by alphabet_index", if I have already sorted the table by name using "alter table"? Thanks a lot for your help.
Shoan
Yes. There is no guarantee the rows are returned sorted, except when you specify an order by clause.
Vinko Vrsalovic