sql - 使用 Postgres 恢复单例查询值

标签 sql postgresql plpgsql postgresql-9.1 sql-server-mars

因为 Postgres 似乎没有每个 UDF(SQL Server does)的多个结果集的功能。返回查询范围单例值的最佳方法是什么?例如,当对 FTS 搜索的结果进行分页时,如果我们可以获得与查询匹配的结果数量(无需使用分页遍历所有页面),它会简化逻辑。

方法一:将 post_count 粘贴到 SELECT 列表中。缺点:重复

方法二: 编写一个单独的 UDF 来获取 post_count 缺点:多个 UDF 调用(我使用这种方法,它使能够显示第一页的延迟加倍)。

方法三:对结果集使用数组,并将 post_count 作为结果集的兄弟放在顶层 缺点:慢得多 - 也许这是由于 array_agg () 函数(是的,我试过这种方法)。

那么对于这个问题是否有更务实的解决方案,如果没有,开发管道中是否有任何东西可以解决这个问题?

最佳答案

我自己反复遇到这个问题,还没有找到一个解决方案。

我最新的方法是将返回的 SET 的第一行定义为元数据。您的方法列表中没有那个,但是. 该应用程序使用第一行进行簿记。实际数据从第二行开始。

明显的弱点:您必须凑合使用您必须在元数据中压缩的任何行定义。不过,简单的总数将适合任何数字或字符串类型。
当然,您必须对应用程序的第一行进行特殊处理。

这个简单的例子从表 foo 中返回行,定义为

CREATE TABLE foo (
  foo_id serial PRIMARY KEY
 ,foo    text
 );

页面大小为 20 行,默认情况下在函数头中预先设置:

CREATE OR REPLACE FUNCTION f_paginate(_max_id int, _limit int = 20
                                                 , _offset int = 0)
  RETURNS TABLE(foo_id int, foo text) AS
$BODY$
BEGIN

SELECT INTO foo_id  count(*)::int
FROM   foo f
WHERE  f.foo_id < _max_id; -- get count

RETURN NEXT;               -- use first row for meta-data

RETURN QUERY               -- actual data starts with second row
SELECT f.foo_id, f.foo
FROM   foo f
WHERE  f.foo_id < _max_id
LIMIT  _limit
OFFSET _offset;

END;
$BODY$
  LANGUAGE plpgsql;

调用:

SELECT * FROM f_paginate(100);

返回:

foo_id | foo
-------+----
86     | <NULL>    <-- first row = meta-data
1      | bar       <-- actual data
2      | baz
... 18 more ...

显然,这种方法可以节省一些带宽,并具有更高的 _limit(页面大小)。只有几行,几乎不值得开销。

另一种方法是您的“方法一”- 冗余添加一列:

CREATE OR REPLACE FUNCTION f_paginate2(_max_id int, _limit int = 20
                                                  , _offset int = 0)
  RETURNS TABLE(foo_id int, foo text, ct bigint) AS
$BODY$
BEGIN

RETURN QUERY
SELECT f.foo_id, f.foo, count(*) OVER ()
FROM   foo f
WHERE  f.foo_id < _max_id
LIMIT  _limit
OFFSET _offset;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

调用:

SELECT * FROM f_paginate2(100);

返回:

foo_id | foo | ct
-------+-----+----
1      | bar | 86
2      | baz | 86
... 18 more ...

在这个简单的例子中,性能非常相似。第一个查询稍快一些,但可能只是因为 count(*) OVER () 减慢了第二个查询。单独运行 count(*) 会更快。

关于sql - 使用 Postgres 恢复单例查询值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12282313/

相关文章:

postgresql - 删除后触发在远程数据库中插入行

mysql - SQL 从表的所有列中删除元素

sql - 如何在查询中包含零计数结果

mysql - 更新表均衡相同 ID 但不同国家/地区的位置

PostgreSQL - 表中的下一个序列值

PostgreSQL 触发器不工作 - 既不在删除之前也不在删除之后

mysql - ORDER BY id DESC 结合 WHERE id < ... 不会使用索引

结果集错误 : Issue knitting RMarkdown with SQL connection

sql - 在 psql 中显示两列而不是两行

postgresql - Postgres 中过程/游标的逻辑问题