使用Knex.js limit()方法时,如何通过单查询获取总记录数?
在Knex.js + PostgreSQL中实现带Limit的查询同时获取总记录数
当然可以,利用PostgreSQL的窗口函数就能在同一条查询里同时拿到分页数据和符合条件的总记录数,完全不用执行两次查询。
核心原理
PostgreSQL支持count(*) over()窗口函数,它会计算所有满足当前查询条件的总记录数,不受limit的限制。把这个函数作为字段加入查询,就能在每条返回的结果里带上总条数。
基础示例
针对你给出的简单查询,修改后的Knex代码如下:
const paginatedData = await knex('project') .select([ '*', // 按需选择字段,避免用*可以明确列出需要的列 knex.raw('count(*) over() as total_count') ]) .limit(50); // 总记录数取第一条结果的total_count即可 const totalRecords = paginatedData.length > 0 ? paginatedData[0].total_count : 0;
复杂查询(带子查询/条件)
如果你的查询包含大量子查询、where条件或关联,写法逻辑完全一致,只需要把窗口函数加入select列表:
const complexPaginatedData = await knex('project') .select([ 'project.id', 'project.name', 'user.username as owner_name', knex.raw('count(*) over() as total_count') ]) .where('project.status', '=', 'published') .where(knex.raw('project.created_at > ?', [new Date('2023-01-01')])) .innerJoin('user', 'project.owner_id', 'user.id') .limit(50); const total = complexPaginatedData[0]?.total_count || 0;
注意事项
- 窗口函数
count(*) over()默认计算全局总数,如果你需要按某个字段分组统计总数,可以添加分区条件,比如count(*) over(partition by project.category_id) - 即使查询结果为空(total_count为0),也要做边界判断避免报错
内容的提问来源于stack exchange,提问作者Edward Harsh
相关产品推荐
相关产品推荐

