I'm trying to figure out the fastest way to get x rows from a table that are offset by x rows and ordered by a date column.
The problem I have is I'm paginating the rows from the query into pages of 10 rows per page, but I only need the nth page.
For example if I only need page 4 from the table, I need to select all the rows:
SELECT * FROM posts ORDER BY date
Then I need to paginate the array using PHP and get the 4th page (if it exists). This is less than ideal as it seems a waste to have to get the whole table.
Is there a better way to query the table in this situation?. For example if I have 10 posts per page and I want the the 4th page, is there a way to offset the query so it starts from the 30th row? (and ordered by date).
You're looking for LIMIT
SELECT * FROM posts ORDER BY date LIMIT 10, 20
Where 10 is offset and 20 is the number of rows
LIMIT is the answer. According to MySQL documentation,
The LIMIT clause can be used to constrain the number of rows returned
by the SELECT statement. LIMIT takes one or two numeric arguments,
which must both be nonnegative integer constants (except when using
prepared statements).
With two arguments, the first argument specifies the offset of the
first row to return, and the second specifies the maximum number of
rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
Related
I'm working on an application that uses a scroll load system of 20 or so results loading into a feed at a time as you scroll. This feed consists of constantly added user generated content. Which means the result set can change per query that is offset by X.
So let's say we load 20 results, then scroll, another 20, and then before scrolling more to load the next 20, another user has uploaded a new piece of content, which effectively would present a duplicate in the next set of 20 results for the feed because we're using OFFSET to get additional results, and the total result set is getting shifted by 1 with this addition of new content that falls into the conditions of the query.
What is the best and most efficient way around this? We've dabbled with using the id of a row in a where condition to prevent duplicate results, and only using limit without offset for new results fetched.. so we could do WHERE id < 170 LIMIT 20, WHERE id < 150 LIMIT 20, WHERE id < 130 LIMIT 20, etc.. to control and prevent duplciates... HOWEVER, this does not work in every possible scenario as our result sets aren't always ordered with the id column ordered by DESC..
Soo.. what other options are there?..
Why are you using the where clause instead of limit with the offset option? Limit can take two arguments. The offset argument seems to do exactly what you want. For instance:
limit 100, 20
Takes 20 rows starting at the 101st row. Then:
limit 120, 20
Takes 20 rows starting at the 121st row. (The offsets start at 0 rather than 1 in MySQL counting.)
The one enhancement that you need to make is to ensure that the sort order for the records is stable. A stable sort is, essentially, one where there are no sort keys with the same value. To make this happen, just make the id column the last column in the sort. It is unique, so if there are any duplicate sort keys, then the addition of the id makes the sort stable.
You might want to try a database solution. On the initial request, create and populate a table. Use that table for the feed.
Make sure the tablename starts with something consistent, like TableToFeedMyApp, and ends with something guaranteed to make it unique. Then set up a scheduled job to find and drop all these tables that were created earlier than whatever you deem to be a certain interval.
well this should be easy for someone---
I am trying to select specific rows in a database
SELECT * FROM customers LIMIT 10,20
but it always returns 20 rows
what is going on, and why does the minimum not have any value?
LIMIT X, Y
means that you get Y results starting from number X+1.
So if you want values from 11 to 20 you need to use:
LIMIT 10, 10
You would want to do limit 10 or lmit 0, 10 for 10 results
The second number of the LIMIT clause is the number of rows to be returned, not the last index. if you only want 10 rows, replace 20 by 10 in your query limit clause.
SELECT *
FROM customers
LIMIT 10, 10
Limit with two arguments (x,y) means you get rows from x+1 to y. From the MySQL Manual:
The LIMIT clause can be used to constrain the number of rows returned
by the SELECT statement. LIMIT takes one or two numeric arguments,
which must both be nonnegative integer constants (except when using
prepared statements).
With two arguments, the first argument specifies the offset of the
first row to return, and the second specifies the maximum number of
rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10;
Retrieve rows 6-15 To retrieve all
rows from a certain offset up to the end of the result set, you can
use some large number for the second parameter.
This statement
retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
With one argument,
the value specifies the number of rows to return from the beginning of
the result set:
SELECT * FROM tbl LIMIT 5;
Retrieve first 5 rows In other words,
LIMIT row_count is equivalent to LIMIT 0, row_count.
I'm creating a pagination with a where clause.
I need to know the true behaviour of the offset.
Is the offset calculated based on all the rows that match the where clause? Or
The offset is calculated like an id and all rows are considered. Eg. If you specify an offset of 5, rows will be returned starting from the 6th row in the table even of the first 4 rows don't match the where clause?
Edit: I want to be sure since the second behaviour would be totally incorrect and cause problems.
Thanks for your answers. I can't comment as my browser fails at javascript and ajax horribly.
Yes the offset is calculated based on all rows that matches the where clause. Just try it.
Are you talking about using the LIMIT clause? LIMIT puts a cap on the number of successful matches, not the total matches. The offset portion of limit is calculated from the matches rather than all eligible rows. MySQL will not necessarily scan rows in a given order and may not scan some rows at all, so it wouldn't short change you rows if a failed match had a lower index.
How do I output data from column, but to be like.. for example - the column is with 40 lines of query results and I want to output only that, that are from 10 to 30 . How to do it with PHP?
For MySQL, you could use a LIMIT offset, maxrows:
SELECT * FROM tbl LIMIT 9,20;
will get you rows 10-30. Note that the offset value is 0 based, hence the 9 rather than 10.
I am trying to implement the pagination in php. I am using the Mysql as back end database. I am trying to implement the pagination logic.
I would be having lots of record. But the user will see only 10 at a time.
Now to show the first page, i do a
SELECT * from USERS LIMIT 10.
Now to get the next 10 and the subsequent 10 records i am not able to write a query. Please help me fetch the in between records to support pagination logic. Also provide if any other suggestions for pagination.
You should use the OFFSET option.
SELECT * FROM Users LIMIT 10 OFFSET 10 (or 20, or 30);
That way you just pass the start position in the request when you hit next (or the page number) and you'll retrieve the records you want.
MySQL's limit feature can take two arguments:
select * from USERS limit 10,10
The above would retrieve 10 rows starting at row 10. Bear in mind that the MySQL row offset is 0 based, not 1. The first argument is the starting row, the second is the page size.
Also, if your page size is consistent, all you need to do is pass in the current page (default to zero). That would then allow you to specify the start row as a page * size.