0

私は次の手順を持っています:

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;

しかし、この手順から結果を返す方法がわかりません。クエリは、外側のカーソル ループ内での実行ごとに 5 行を返します。クエリの実行ごとにこれらの 5 つの行を取得するにはどうすればよいですか?

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();

関数からの復帰に関するマニュアル。CREATEFUNCTION
に関するマニュアル。


巨大な結合の小さなスライスを取得します

(コメントへの回答。)
実際に結合全体を評価せずに、巨大な結合の小さなスライスを選択する方法はたくさんあります。ほとんどの場合、それについて心配する必要はありません。たとえば、これを自宅で実行します。

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 に答える