因为 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/