73

this seems like very simple maths but somehow, my brain cant think ...

i am trying to implement pagination and will need to calculate the item offset to use in limiting my result set. i am having problems calculating what index the first item of the page should have.

eg.

with 1 page having 10 items

page 1 will have items 1 - 10
page 2 ............... 11 - 20
page 3 ............... 21 - 30

i thought of

offset = page * itemsPerPage + 1

but this will not be the case for page 1. there must be a formula for this? am using PHP/Zend_Paginator/Doctrine2 but this should be language independent

wonder if this should be in the the maths stack exchange site

Jiew Meng
  • 84,767
  • 185
  • 495
  • 805

13 Answers13

133

Use offset = (page - 1) * itemsPerPage + 1.

Ayyappan Sekar
  • 11,007
  • 2
  • 18
  • 22
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • 35
    Should it not be: offset = (page - 1) * itemsPerPage As result number 1 would never be shown otherwise? – Ultimate Gobblement Aug 19 '10 at 10:56
  • 2
    Hi do you mean offset = (page_number - 1) * itemsPerPage; If so won't the result generate numbers bigger than the itemsPerPage number? – Jam Feb 07 '13 at 20:59
  • I meant to answer the question while taking Jiew’s example into account. He’s obviously trying to calculate the first item number for each page; so firstItemForPage(1)=(1-1)·10+1=1, firstItemForPage(2)=(2-1)·10+1=11, and so on. – Gumbo Feb 07 '13 at 21:42
  • 16
    ```$offset = ($pageLimit * $page) - $pageLimit;``` I have been using the above more than a year now. You can also try it out. – Olotin Temitope Oct 09 '17 at 21:42
52

Honestly depends. I'm no PHP person, but I'll put both out there. If you are pulling your records in to some form of collection (list, array, etc.) then your formula should be:

offset = (page - 1) * itemsPerPage

This is because most (again, I'm not a PHP person) arrays and lists use 0 for their first element. If they do not use 0 for their first element and/or you're pulling from a table or something else where the IDs start at 1, then it should be:

offset = (page - 1) * itemsPerPage + 1

I hope that's clear and helps.

XstreamINsanity
  • 4,176
  • 10
  • 46
  • 59
16
  start = (page - 1) * itemsPerPage + 1
  end = totalItems

  if (itemsPerPage < totalItems) {
    end = itemsPerPage * page
    if (end > totalItems) {
      end = totalItems;
    }
  }

  // e.g. "21-30 of 193 items"
  start + '-' + end + ' of ' + totalItems + ' items'
mynameistechno
  • 3,526
  • 1
  • 37
  • 32
7

Using JS as an example, for progressive web app people...

JS arrays have the prototype method .slice(start, end) overview here it takes a start index and an end index as arguments.

I found the easiest way to calc both indexes is as follows;

Start Index

var start =  parseInt((selectedPage - 1) * resultsPerPage);

End Index

var end = parseInt(selectedPage * resultsPerPage);

Execution

var myPaginatedArray.slice(start, end);
Mark Carpenter Jr
  • 812
  • 1
  • 16
  • 32
6

I think this one is perfect and covers all scenario.

$offset = ($pageLimit * $page) - $pageLimit;
T J
  • 42,762
  • 13
  • 83
  • 138
ManojP
  • 6,113
  • 2
  • 37
  • 49
4

Thought I would add the following for displaying text like e.g:

Viewing 21-30 of 32 items.

In this example:

itemsPerPage = 10
page = 3
totalItems = 32

And there would be a total of 4 pages where the last page only has 2 items to display. The following worked for me:

(page  - 1) * itemsPerPage + 1 + "-" +
     Math.Min((page - 1) * itemsPerPage + itemsPerPage , totalItems ) + " of " +
     totalItems + " items."

Sorry that is in C# strictly but the idea should be clear. Math.Min(x, y) returns the lower number of two parameters. There is probably an easier solution to calculate the upper bound without using Math.Min.

Audwin Oyong
  • 2,247
  • 3
  • 15
  • 32
Patrick Borkowicz
  • 1,206
  • 10
  • 19
2

A simple pagination equation that covers all scenerio will be:

$page = $_GET['page'];

$items_per_page = 20;  //for example

$offset = 0;  //initial offset

if ($page != 1) {
   $offset = ($page * $items_per_page) - $items_per_page;

}

Given items per page = 5

OUTPUT

when page = 1, offset = 0

when page = 2, offset = 5

when page = 3, offset = 10

when page = 4, offset = 15 . . .

Acheme Paul
  • 1,194
  • 15
  • 19
2

Use following formulae, these work well:

  • For start_index: (page_number - 1) * per_page
  • For end_index: start_index + (per_page - 1) (Usually we specify simply per_page - 1 in SQL)
page_number | start_index | end_index | per_page | formula for start_index
    1       |    0        |   24      |    25    |   (page_number - 1) * per_page 
    2       |    25       |   49      |    25    |   (page_number - 1) * per_page 
    3       |    50       |   99      |    25    |   (page_number - 1) * per_page 
Akshay Lokur
  • 6,680
  • 13
  • 43
  • 62
1

$offset = $pageNumber * $limit - $limit;

Page 1:

$pageNumber = 1
$limit = 10
$offset = 1 * 10 - 10 = 0

The offset for page 1 is 0, as it is the first page, and there is no need for an offset.


Page 2:

$pageNumber = 2
$limit = 10
$offset = 2 * 10 - 10 = 10

The offset for page 2 is 10, as we have already displayed the items from page 1, so we need to skip the first 10 items.


Page 3:

$pageNumber = 3
$limit = 10
$offset = 3 * 10 - 10 = 20

The offset for page 3 is 20, as we have already displayed the items from pages 1 and 2, so we need to skip the first 20 items.

ismavolk
  • 115
  • 2
  • 3
0

use this

$row_page = 5; //items per page

if(isset($_GET['p'])){
    $page_num = $_GET['p'];
} else {
    $page_num = 0;
}

$offset = ( $page_num ) * $row_page;

$cn = 31;

$pg = (int)ceil($cn / $row_page);

for ($i = 1; $i <= $pg; $i++){
    echo "<br/><a href='?p=$i'>".$i;
}
0

I have faced this before in Angular 4, this is an edit of a piece of template with a list with pagination made simpler:

<div *ngFor="let item of pagedItems; let i = index">
  <div class="item-caption">
    Item {{(currentPage - 1) * itemsPerPage + (i + 1)}} of {{totalItemsDownloaded}}
  </div>
  <div class="item-name">{{item.name}}</div>
</div>

I have always handy currentPage as a result of clicking on Prev & Next buttons but initialized with 1, itemsPerPage as an App setting and totalItemsDownloaded is the count of total items the WebAPI call reported.

I hope it helps

Sparker73
  • 303
  • 2
  • 10
0

following is standard and easiest way to calculate the offset when every page event is triggered.

offset = ((pageNumber-1) * itemPerPage + 1)-1;

pageNumber = 1
itemPerPage = 10
offset  = ((pageNumber-1) * itemPerPage + 1)-1;
console.log("offset for 1st page", offset)

pageNumber = 2
offset  = ((pageNumber-1) * itemPerPage + 1)-1;
console.log("offset for 2nd page", offset)

pageNumber = 3
offset  = ((pageNumber-1) * itemPerPage + 1)-1;
console.log("offset for 3rd page", offset)
0

PHP code for setting offset.

$offset = ($page - 1) * $limit ;
Ankit Jain
  • 11
  • 2