在对来自 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 或更高版本中,规划器可能会在开始工作之前内联那些类似子查询的内容。)不在这里。
WHERE
子句(和JOIN
条件,尽管在您的示例中没有)过滤来自基表的合格行。 其余部分基于过滤后的子集。
(2. GROUP BY
和聚合函数会放在这里。)不在这里。
( 3. 其他 SELECT
列表表达式根据分组/聚合列进行评估。) 不在这里。
窗口函数的应用取决于
OVER
子句和函数的框架规范。简单的count(*) OVER()
是基于所有符合条件的行。排序方式
(6. DISTINCT
或 DISTINCT ON
会放在这里。)不在这里。
LIMIT
/OFFSET
根据已建立的顺序应用以选择要返回的行。
LIMIT
/OFFSET
随着表中行数的增加而变得越来越低效。如果您需要更好的性能,请考虑替代方法:
获得最终计数的备选方案
获取受影响行数的方法完全不同(不是OFFSET
和LIMIT之前的完整计数
已应用)。 Postgres 有内部记账多少行受最后一个 SQL 命令影响。一些客户端可以访问该信息或自己计算行数(如 psql)。
例如,您可以在执行 SQL 命令后立即检索 plpgsql 中受影响的行数:
GET DIAGNOSTICS integer_var = ROW_COUNT;
或者您可以使用 pg_num_rows
in PHP .或其他客户端中的类似功能。
相关:
关于php - 在应用 LIMIT 之前获取结果计数的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/156114/