php - 在应用 LIMIT 之前获取结果计数的最佳方法

标签 php sql postgresql window-functions sql-limit

在对来自 DB 的数据进行分页时,您需要知道将有多少页面来呈现页面跳转控件。

目前我通过运行两次查询来做到这一点,一次包含在 count() 中以确定总结果,第二次应用限制以获取我需要的结果当前页面。

这似乎效率低下。有没有更好的方法来确定在应用 LIMIT 之前会返回多少个结果?

我正在使用 PHP 和 Postgres。

最佳答案

纯 SQL

自 2008 年以来情况发生了变化。您可以使用 window function在一个查询中获得完整的计数有限的结果。与 PostgreSQL 8.4 in 2009 一起介绍.

SELECT foo
     , <b>count(*) OVER() AS full_count</b>
FROM   bar
WHERE  <some condition>
ORDER  BY <some col>
LIMIT  <pagesize>
OFFSET <offset>;

请注意,这可能比没有总数的情况要昂贵得多。必须对所有行进行计数,并且从匹配索引中仅获取顶行的可能捷径可能不再有用。
与小表或 full_count <= OFFSET + LIMIT 无关。对于更大的 full_count 来说很重要。

极端情况:当 OFFSET 至少与基本查询的行数一样多时,不返回任何行。所以你也没有得到 full_count。可能的替代方案:

SELECT 查询中的事件序列

(0。CTE 是单独评估和实现的。在 Postgres 12 或更高版本中,规划器可能会在开始工作之前内联那些类似子查询的内容。)不在这里。

  1. WHERE 子句(和 JOIN 条件,尽管在您的示例中没有)过滤来自基表的合格行。 其余部分基于过滤后的子集。

(2. GROUP BY 和聚合函数会放在这里。)不在这里。

( 3. 其他 SELECT 列表表达式根据分组/聚合列进行评估。) 不在这里。

  1. 窗口函数的应用取决于 OVER 子句和函数的框架规范。简单的 count(*) OVER() 是基于所有符合条件的行。

  2. 排序方式

(6. DISTINCTDISTINCT ON 会放在这里。)不在这里。

  1. LIMIT/OFFSET 根据已建立的顺序应用以选择要返回的行。

LIMIT/OFFSET 随着表中行数的增加而变得越来越低效。如果您需要更好的性能,请考虑替代方法:

获得最终计数的备选方案

获取受影响行数的方法完全不同(不是OFFSETLIMIT之前的完整计数已应用)。 Postgres 有内部记账多少行受最后一个 SQL 命令影响。一些客户端可以访问该信息或自己计算行数(如 psql)。

例如,您可以在执行 SQL 命令后立即检索 plpgsql 中受影响的行数:

GET DIAGNOSTICS integer_var = ROW_COUNT;

Details in the manual.

或者您可以使用 pg_num_rows in PHP .或其他客户端中的类似功能。

相关:

关于php - 在应用 LIMIT 之前获取结果计数的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/156114/

相关文章:

postgresql - 手动创建用于在 PostgreSQL 10 中发布的复制槽

php - 从 laravel 中的路由将参数传递给 Controller

sql - 如何遍历从 SQL 中的 select 语句返回的行列表?

sql - Postgresql 组中的前 N ​​项 WHERE N 是可变的

sql - 保持列与 Postgres 中的另一列同步

postgresql - Postgres 覆盖系统函数

php - 隐藏在 Woocommerce 中默认选择的具有唯一变体的可变产品下拉列表

php - 如何使用相同名称的输入类型更新多个 mysql 行

php - 如何在 HTML 片段中注入(inject)字符串

java - 如何在 TomCat jdbc 池的帮助下杀死运行超过 1 秒的 sql 查询?