Laravel中按updated_at分页重复,需实现指定时间段排序咨询
Laravel按updated_at分页出现重复数据,按id分页正常
在Laravel项目中,按updated_at字段降序分页查询时,部分页面数据会出现重复;但按VoucherID(id字段)降序分页时,数据显示正常无重复。
按updated_at降序分页(存在重复)
page 4 = id=12 id=13 id=14 id=15 id=16 id=17 id=18 page 3 = id=2 id=3 id=4 id=5 id=6 id=7 id=8 id=9 id=1 id=11 page 2 = id=25 id=26 id=27 id=28 id=29 id=30 id=31 id=32 id=33 id=10 page 1 = id=37 id=36 id=35 id=34 id=2 id=3 id=4 id=5 id=6 id=8
按id降序分页(正常)
page 4 = id=7 id=6 id=5 id=4 id=3 id=2 id=1 page 3 = id=17 id=16 id=15 id=14 id=13 id=12 id=11 id=10 id=9 id=8 page 2 = id=27 id=26 id=25 id=24 id=23 id=22 id=21 id=20 id=19 id=18 page 1 = id=37 id=36 id=35 id=34 id=33 id=32 id=31 id=30 id=29 id=28
需求
实现按updated_at字段的日期及00:00:00至11:59:00的时间段排序,同时保证分页正常无重复。
现有相关代码
VoucherController
public function index(ManageVoucherRequest $request) { return view('backend.voucher.index') ->withvouchers($this->voucherRepository->getActivePaginated(10, 'updated_at', 'desc')); }
VoucherRepository
public function getActivePaginated($paged = 25, $orderBy = 'created_at', $sort = 'desc') : LengthAwarePaginator { return $this->model ->orderBy($orderBy, $sort) ->paginate($paged); }
解决方案
问题根源是:当多条记录的updated_at值相同时,数据库对这些记录的排序顺序不稳定——每次查询时它们的相对位置可能变化,导致分页时部分记录跨页重复。而id是唯一字段,按id排序时所有记录的顺序固定,不会出现重复。
要解决这个问题,需保证排序规则的唯一性:在按updated_at排序的基础上,追加按id字段排序。这样即使updated_at相同,id的唯一性也能让记录顺序固定,分页就不会出现重复。
修改VoucherRepository中的getActivePaginated方法:
public function getActivePaginated($paged = 25, $orderBy = 'created_at', $sort = 'desc') : LengthAwarePaginator { return $this->model ->orderBy($orderBy, $sort) ->orderBy('id', $sort) // 新增按id排序,保证顺序唯一 ->paginate($paged); }
如果需要严格按updated_at的日期和上午时间段(00:00:00至11:59:00)排序,可以进一步调整排序逻辑:
public function getActivePaginated($paged = 25, $sort = 'desc') : LengthAwarePaginator { return $this->model ->orderByRaw("DATE(updated_at) {$sort}") ->orderByRaw("TIME(updated_at) {$sort}") ->orderBy('id', $sort) ->paginate($paged); }
这样既满足了按updated_at的日期和时间段排序的需求,又保证了分页的稳定性,不会出现重复数据。
内容的提问来源于stack exchange,提问作者Md Amirul
相关产品推荐
相关产品推荐

