我有一个带有ID,时间和PostGIS点对象列的表。该表在不同时间为每个ID包含多个点。我想找到一个ID的点集到另一个ID的点集的平均距离,针对同一时间发生的每个点,并求出所有其他ID的点集与该原始ID的点集的平均值。>
到目前为止,我具有此功能:
CREATE TYPE score AS (id int, dist float);
CREATE OR REPLACE FUNCTION avgdist(id1 int) RETURNS TABLE (id int, dist float) LANGUAGE plpgsql AS
$func$
DECLARE
scores score;
id2 int;
set2 record;
begin
id2:= 0;
IF (id1 = id2 ) THEN
id2:= 1;
END IF;
FOR set2 IN
SELECT my_table.id, my_table.time, my_table.geom FROM my_table WHERE my_table.id = id2 loop
id2:= id2 + 1;
CONTINUE WHEN id1 = id2;
EXECUTE 'WITH origin AS (SELECT time, id, geom FROM my_table WHERE id = $1)
SELECT id, avg(ST_Distance(origin.geom, $2))
FROM origin WHERE origin.time = $3
group by origin.id
ORDER BY id'
INTO scores
USING id1, set2.geom, set2.time;
end loop;
RETURN;
end
$func$;
使用select * from avgdist(2)
调用此函数时,没有得到任何结果,与slect avgdist(2)
相同。当我在带有插入值的psql中在自己的execute中运行查询时,我确实得到了结果。
我是第一次在sql中创建函数,所以当该表没有名称时,我并不真正了解如何将分数放入返回表中。而且我似乎无法使用RETURN QUERY
,因为我需要返回循环中所有查询的结果。
在此方面的帮助将不胜感激,或者有更好的方法来实现我想要的结果而不会循环?
答案 0 :(得分:2)
还有更多问题:
子句RETURNS TABLE
定义OUT
变量。您可以使用这些变量。
CREATE OR REPLACE FUNCTION foo()
RETURNS TABLE (r1 int, r2 int)
-- you don't need aux variables for result
...
r1 := 10; r2 := 10;
RETURN NEXT;
EXECUTE INTO
只能存储动态查询结果的第一行(或值)。
RETURN
停止功能评估。您应该使用RETURN NEXT
或RETURN QUERY
。
FOR x, y IN SELECT ..
LOOP
-- when only first row of result is interesting
EXECUTE '..' INTO r1, r2 USING x, y;
RETURN NEXT;
END LOOP
或带有RETURN QUERY EXECUTE
FOR x, y IN SELECT ..
LOOP
RETURN QUERY EXECUTE '..' USING x, y;
END LOOP
我不理解您的代码,但是看起来您不需要使用动态SQL-EXECUTE
命令。仅当在SQL标识符上有变量时,才需要动态SQL。没有这种情况。同样的情况-为什么使用 CTE WITH
子句。不必要-可能产生负面影响(不必要的实现-由PostgreSQL 12修复)。仅使用RETURN QUERY
(不使用EXECUTE
)并将查询作为查询(而不是字符串)传递。
有关这些命令的文档很好-https://www.postgresql.org/docs/current/plpgsql-control-structures.html#PLPGSQL-STATEMENTS-RETURNING