在MySQL中使用JOINed ORDER子句进行分页

时间:2018-11-13 08:45:56

标签: mysql sql join pagination

在对通过查询联接表构建的数据集进行分页时遇到一些麻烦。

我的产品表如下:

id   | sort_order
-----------------
1    | 5
2    | 4
3    | 0
4    | 0
5    | 4
...

我加入的股票表如下:

id | product_id | start_date
----------------------------
1  | 1          | 2018-12-14
2  | 1          | 2019-01-28
3  | 2          | 2018-12-26
4  | 3          | 2018-12-28
5  | 4          | 2019-01-12
6  | 4          | 2019-01-14
7  | 5          | 2020-01-10
...

我想对我的产品列表进行分页,但是,我希望将其排序如下:

  • 首先,通过sort_order
  • 第二,最早的start_date与之相关。

我最初是从cursor pagination开始的,但这导致了重复的结果,尽管总页数(在游标到末尾之后)是正确的-这意味着肯定有丢失的行,这些行从未被提取过

然后我求助于基于页面的分页(目前也可以),但这也会导致重复和大量页面。

我对如何继续执行此操作非常困惑。

我的基于偏移量的分页SQL(由Sequelize生成)如下:

SELECT
    `Product`.`id` AS `id`,
    `Product`.`sort_order` AS `sortOrder`,
    `availability`.`id` AS `availability.id`,
    `availability`.`product_id` AS `availability.productId`,
    `availability`.`start_date` AS `availability.startDate`
FROM
    `product` AS `Product`
LEFT OUTER JOIN `stock` AS `availability` 
                 ON `Product`.`id` = `availability`.`productId`
ORDER BY
    sort_order = 0,
    sort_order
LIMIT 0, 10

对于上面的数据集,我希望以下几点:

id   | sortOrder | `availability.id` | `startDate`
--------------------------------------------------
1    | 5         | 1                 | 2018-12-14
2    | 4         | 3                 | 2018-12-26
5    | 4         | 7                 | 2020-01-10
3    | 0         | 4                 | 2018-12-28
4    | 0         | 5                 | 2019-01-12

1 个答案:

答案 0 :(得分:1)

由于JOIN到一个表中每个product_id具有多个值,因此您得到了重复。您需要将其限制为一个值,并基于排序标准,该条件应为与最小start_date关联的值。您可以使用JOIN表的子查询来做到这一点:

SELECT
    `Product`.`id` AS `id`,
    `Product`.`sort_order` AS `sortOrder`,
    `availability`.`id` AS `availability.id`,
    `availability`.`product_id` AS `availability.productId`,
    `availability`.`start_date` AS `availability.start_date`
FROM
    `product` AS `Product`
LEFT JOIN (SELECT id, product_id, start_date
           FROM`stock` s
           WHERE start_date = (SELECT MIN(start_date) 
                               FROM stock s1 
                                WHERE s1.product_id = s.product_id)
           ) AS `availability` 
    ON `Product`.`id` = `availability`.`product_id`
ORDER BY
    sort_order = 0,
    sort_order,
    availability.start_date
LIMIT 0, 10

输出示例数据:

id  sortOrder   availability.id     availability.productId  availability.start_date
1   5           1                   1                       2018-12-14
2   4           3                   2                       2018-12-26
5   4           7                   5                       2020-01-10
3   0           4                   3                       2018-12-28
4   0           5                   4                       2019-01-12

Demo on SQLFiddle