0

I have the following procedure :

CREATE OR REPLACE FUNCTION findKNN()
RETURNS Text AS $body$
DECLARE
    cur refcursor;
    tempcur refcursor;
    gid_ integer;
    _var1 integer;
    _var2 integer;
BEGIN
    open cur for execute('select gid from polygons');
    loop
    fetch cur into gid_;
    open tempcur for SELECT g1.gid , g2.gid FROM polygons AS g1, polygons AS g2
    WHERE g1.gid = gid_  and g1.gid <> g2.gid ORDER BY g1.gid , ST_Distance(g1.the_geom,g2.the_geom)
        LIMIT 5;
             loop
                 fetch tempcur into _var1 , _var2;
                     -- how to return _var1 , _var2 here ? 
                 end loop;
          end loop;
                close cur;
    END;
$body$
LANGUAGE plpgsql;

But I don't know how to return the result out of this procedure. The query returns 5 rows for each execution within outer cursor loop. How can I retrieve these five rows for each query execution?

4

1 回答 1

3

除非您尝试做一些不属于您的问题的更复杂的事情,否则您可以从根本上简化为:

CREATE OR REPLACE FUNCTION find_knn()
    RETURNS TABLE(gid1 integer, gid2 integer)  AS
$body$
BEGIN

    RETURN QUERY
    SELECT g1.gid , g2.gid
    FROM   polygons g1
    JOIN   polygons g2 ON g1.gid <> g2.gid
    -- WHERE  g1.gid = <some_condition>  -- ???
    ORDER  BY g1.gid, st_distance(g1.the_geom, g2.the_geom)
    LIMIT  5;

END;
$body$    LANGUAGE plpgsql;

甚至:

CREATE OR REPLACE FUNCTION find_knn()
    RETURNS TABLE(gid1 integer, gid2 integer)  AS
$body$
    SELECT g1.gid , g2.gid
    FROM   polygons g1
    JOIN   polygons g2 ON g1.gid <> g2.gid
    -- WHERE  g1.gid = <some_condition>  -- ???
    ORDER  BY g1.gid, st_distance(g1.the_geom, g2.the_geom)
    LIMIT  5;
$body$    LANGUAGE sql;

称呼:

SELECT * FROM x.find_knn();

关于从函数返回的手册。
关于CREATE FUNCTION的手册。


检索一个巨大连接的一小部分

(评论的答案。)
有很多方法可以在不实际评估整个连接的情况下选择一个巨大连接的一小部分。在大多数情况下,您甚至不必担心它。例如,在家里运行这个:

EXPLAIN ANALYZE
SELECT *
FROM   huge_tbl t1
CROSS  JOIN huge_tbl t2
LIMIT  5

您将看到只处理 5 行,而不是整个交叉连接。CTE
也是如此:

WITH a AS (
    SELECT *
    FROM   huge_tbl t1
    CROSS JOIN huge_tbl t2
    )
SELECT *
FROM   a
LIMIT  5

一些限制适用。我引用了优秀的手册

PostgreSQL 的实现只评估 WITH 查询的行数,与父查询实际获取的行数一样多。

为了绝对确定,您可以在源头应用LIMIT(或合适的WHERE条款):

SELECT *
FROM   (SELECT * FROM huge_table LIMIT 1) t1
CROSS  JOIN (SELECT * FROM huge_table LIMIT 5) t2;
于 2012-05-06T13:35:12.057 回答