简体   繁体   中英

How to improve SQL query for pagination?

I'm working with the database and servlets, there was such a problem. I need to receive data from the database of 6 pieces per page, for this I made such a request

SELECT *, COUNT(*) AS 'count' 
FROM product
INNER JOIN product_category
  on product.product_category_id = product_category.id 
INNER JOIN  company_manufacturer_product 
  on product.company_manufacturer_product_id =
     company_manufacturer_product.id
GROUP BY 1 LIMIT 6 OFFSET 0;

where 6 is the maximum number of items per page and 0 is the page number multiplied by the maximum quantity of goods. But with such an implementation on the second page I have duplicate products how can i improve it?

The part of the code where I form the request:

StringBuilder startResponse = new StringBuilder("SELECT *, COUNT(*) AS 'count' FROM product " +
                "INNER JOIN product_category on product.product_category_id = product_category.id " +
                "INNER JOIN company_manufacturer_product on product.company_manufacturer_product_id=company_manufacturer_product.id");
if (nonNull(form.getProductMax()) && nonNull(form.getPage())) {
            startResponse.append(" LIMIT ").append(form.getProductMax()).append(" OFFSET ").append(form.getPage() * form.getProductMax());
        }

My database respone without LIMIT and OFFSET:

在此处输入图片说明

My database respone when I use the query that described above, this request is sent to the database when I turn to the first page with the goods: 在此处输入图片说明

When I turn to the second page with goods, I send such a request to the database

SELECT * , COUNT(*) AS 'count' 
FROM product 
INNER JOIN product_category
  on product.product_category_id = product_category.id
INNER JOIN company_manufacturer_product 
  on product.company_manufacturer_product_id = 
     company_manufacturer_product.id
GROUP BY 1 LIMIT 6 OFFSET 6;

and i have response like that:

在此处输入图片说明

I can not understand what the problem is. I have to use requests through COUNT! How prove it?

Not against the solution of this question, according to the above method, adding order by to original sql can solve the problem. But I think I have a better practice for pagination: using parameters like has_more , last_product_id and limit_num to connect clients with server.

has_more indicates more data in server whether or not left; last_product_id indicates the id of last response data; limit_num indicates the number of per page.

So, client can using has_more to determine sending a request or not, if it is, client sends a request with last_product_id and limit_num to server; and for server, the sql can be this:

select * from table where id < $last_product_id order by id desc
limit $limit_num + 1; =>$datas

And, count($datas) and $limit_num to calculate the value of has_more and last_product_id :

$has_more = 0;
$data_num = count($datas);
if ($data_num > $page_limit) {
    $has_more = 1;
    array_pop($datas);
    $data_num--;
}

$last_product_id = end($datas)['id'] ?? 0; 

SELECT *,COUNT(product.id)作为'count',来自产品INNER JOIN在product.product_category_id上的product_category = product_category.id INNER JOIN company_manufacturer_product在product.company_manufacturer_product_id = company_manufacturer_product.id上按product.id分组按product.id进行订购SET LIMIT 6 OFF 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM