给出简单的pl / pgsql函数:
CREATE OR REPLACE FUNCTION foo (point geometry
, OUT _street text
, OUT _gid int
, OUT distance real)
AS $$
BEGIN
SELECT min(distance(point,geom)) as dist, gid, name into distance, _gid, _street
from streets
where geometria && Expand(point,0.001) group by gid, name order by dist limit 1;
END;
$$ LANGUAGE plpgsql;
导致类似于:
geobase=# select foo(GeomFromText('POINT(-99.124191496999 19.3490666368031)',4326));
foo
-------------------------------------------------
("PASEO DE LOS FRAMBOYANES",345483,0.000118338)
哪个好,除了我希望更类似于此的事实:
_street | _gid | distance
--------------------------+--------+-------------
PASEO DE LOS FRAMBOYANES | 345483 | 0.000118338
我尝试过使用RETURN
子句的变体,将其定义为rowtype,record和even table,但我总是得到一个元组或数组,如示例中所示。关于如何以类似于表格的方式获得结果的任何线索?
答案 0 :(得分:1)
试试select * from foo(GeomFromText('POINT(-99.124191496999 19.3490666368031)',4326));
?
答案 1 :(得分:0)
问题已被多次回答。要分解返回的行类型,请使用
SELECT * FROM foo( ... );
喜欢这里:
但还有更多。
您的函数具有较少混淆语法,不易出错且简化:
CREATE OR REPLACE FUNCTION foo (_point geometry)
RETURNS TABLE (street text, gid int, distance real) AS
$func$
BEGIN
RETRUN QUERY
SELECT s.name, s.gid, distance(_point, s.geom)
FROM streets s
WHERE s.geometria && expand(_point, 0.001)
ORDER BY 3
LIMIT 1;
END
$func$ LANGUAGE plpgsql;
由于您有ORDER BY ... LIMIT 1
,因此您根本不需要min()
和GROUP BY
。
注意我如何对所有列进行表限定以避免命名冲突。
有一个微妙的区别 :如果查询找到 没有行 ,您的原始文件会返回一行为NULL而值,而我的函数实际上不返回任何行。通常情况下,您会想要后者。
与等效的简单SQL函数相同:
CREATE OR REPLACE FUNCTION foo (_point geometry)
RETURNS TABLE (street text, gid int, distance real) AS
$func$
SELECT s.name, s.gid, distance(_point, s.geom)
FROM streets s
WHERE s.geometria && expand(_point, 0.001)
ORDER BY 3
LIMIT 1
$func$ LANGUAGE sql;
但是对于大桌来说效率不高。您对PostGis中的 KNN(k-最近邻居)搜索感兴趣: