select inbetween elements in mysql? - php

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.

Related

What is the difference between chunk and pagination in Laravel?

I already read some article but I am still confused.
I n pagination it will execute a query when load a page but what happen in chunk ?
I read https://laravel-school.com/posts/laravel-pagination-vs-chunk-51 this article and so on.
Now pagination works on a per page basis. So if you for example have 100 records and you retrieve 10 records per page you need to perform 10 queries to get all results. However since it's pagination you have a page number you use to determine which records you will return. For example page 3 will return the records 21-30 and so on. Here you will always only load 10 records in memory and return them. Query wise this works with a limit and offset to determine the correct records.
Now looking at chunk it's actually a bit different. So if we still take the 100 records and we chunk them by 10 records we still parse all the 100 records. However it will only load 10 records in memory at a time. So it's using a similar query approach using limit and offset, however it will eventually return all results, but in batches/chunks instead of only return 1 set of records.
The documentation also does a good job of explaining this: https://laravel.com/docs/9.x/eloquent#chunking-results

How can I write an SQL query offset by x rows

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

MySQL Query Result Offset With Limit With New Result Possibility?

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.

MySQL Queries before NOW

Now I've read on this fantabulous site about how to check if the timestamp that is in your database is before now(), and that answers part of my question.
But the remainder of my question still eludes me:
How can you not only check for timestamps BEFORE now(), but also put a cap on how many before now are queried?
I have a database that is acting as a guestbook, and the output is a flash piece that looks like a post-it board. you fill out a form, and the submission immediately "tacks" itself to the post-it board. The problem is that when you first load the page, it will load every single post starting from id-0 to id-5,000,000 and so on and so forth.
I would like to put a cap on how many are loaded so the query looks at the following things:
What's the current timestamp?
Go back in time (for example) 10 entries ago
Post from THAT point on
The fields I have in my database are: id, comments, timestamp
EDIT
I'm looking at some of the answers, and I would like to ask about the LIMIT. If I put a limit on the queries, will I still be able to query posts that are PAST now?
Example: Say there are two people viewing the site at the same time. One visitor posts a comment into the database. I want person 2 to still be able to the see that comment pop up on his end.
The flash post-it area runs off a php script that queries the database and exports it into an XML format that Flash can read. Every 5 seconds, the flash re-queries the database to check for more posts.
If I put the Limit on the query, will I still be able to grab NEW entries on the fly? I just want the LIMIT to generate a starting point offset from ground zero
I think what you are looking for is called Limit
You just put it at the end of your statement and the query will return the amount of results you wanted
YOUR QUERY LIMIT 0,10
This will return 10 first results
SELECT * FROM
(SELECT ... WHERE dt<NOW() ORDER BY dt DESC LIMIT 10) a
ORDER BY a.dt ASC
or
SELECT ... WHERE dt<NOW() ORDER BY dt DESC LIMIT 10
check which is the more suitable for you.

How to perform page control?

I mean what the most efficient way to get information about the quantity of your page's items and make sql query with LIMIT that you need. or I should get all items and then crop array with php functions?
now I do 2 queries: first to count all items and second to get items that I need with LIMIT.
OK, I'll be more concrete. For example I need to show a question on my page and 20 answers to this question. At the bottom there shold be page control: links to the next, prev page and so on. I want to show proper number of links (number of answers/20) and when I go to any link I want to recieve proper answers (for example 41 to 60 on the 3d page). So what's the best way to get number of items (answers) to show proper number of links and to get proper answers for each link?
I guess your'e trying to say you want to know how many items/answers there is in the query but only read up to 20 items at at time, for pagination.
Firstly: You really should look for a pagination package; lots and lots of people have had the same problem before and there probably exists both free/opensource and proprietary solutions for your programming language and framework. (If you say what language you are using I'm sure someone can reccomend a solution for you.)
Anyway, I know I like to know how things work, so this is how it usually does:
As far as I know the pagination code calculates the pages by doing one query using select count(*) from tblX where something divide this number with the items-per-page number and use ceiling (e.g. 4.1 => 5).
For listing the results per page a new query is required; don't worry the count query is terribly much faster than getting every result discarding the ones you don't need DO NOT DO THAT (that's the recipie for becoming the top story on this page). Something like select * from tblX where something limit Y offset Z where Y is the number of items per page, and Z is the the (requested_page - 1)*Y; page 1 will have offset 0, page 2 have offset 20 (if thats what Y are) etc..
But do not try to implement this manually, it's unneccesary, tedious and error prone, much better to use your time customizing a readymade solution.
I'm assuming you want a count of the number of rows you'll be reading so as to do some pagination or similar? I don't understand your need for the LIMIT in the context of your question. However, if you just want a count of how many rows have been found, use one of the following.
You select the count of all rows such as:
select count(*) as counted, name, address
from contact
Or found rows:
SELECT SQL_CALC_FOUND_ROWS, name, address
from contact
This may be mysql specific I'm not sure.
Update:
For pagination you would do something like the following - (Psuedocode)
$rows = array($result)
$num_rows = sql_calc_found_rows
$per_page = 20
$pages = ceil($num_rows / $per_page)
page
$rows_this_page = array()
$rows_this_page = get_values($rows, (min index)$page_number * $per_page - $per_page, (max index)$page_number * $per_page - 1)

Categories