使用Postgres获取单个每查询值的值

时间:2012-09-05 13:15:58

标签: sql postgresql plpgsql postgresql-9.1 mars

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

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

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

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

对于这个问题,是否有一个更实用的解决方案,如果没有,那么开发流程中是否还有什么可以解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

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

我的最新方法是将返回的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(*)的单独运行速度更快。