PL/PGSQL 总是 returns 数组或数组列表
PL/PGSQL always returns array or list of arrays
给定简单的 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
子句的变体,将其定义为行类型、记录甚至 table,但我总是得到示例中所示的元组或数组。关于如何以类似于 table?
的方式获得结果的任何线索
尝试select * from foo(GeomFromText('POINT(-99.124191496999 19.3490666368031)',4326));
?..
问的问题已经回答了很多次了。分解返回的行类型:
SELECT * FROM foo( ... );
点赞:
但还有更多。
您的函数具有更少的语法混乱、更不容易出错和简化:
CREATE OR REPLACE FUNCTION foo (_point geometry)
RETURNS TABLE (street text, gid int, distance real)
LANGUAGE plpgsql 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$;
既然你有ORDER BY ... LIMIT 1
,你根本不需要min()
和GROUP BY
。
请注意我如何 table 限定所有列以避免命名冲突。
有一个细微差别:如果查询发现没有行你原来的returns一行用NULL值代替,而我的函数居然returns没有一行。通常,您会想要后者。
与等效的简单 SQL 函数相同:
CREATE OR REPLACE FUNCTION foo (_point geometry)
RETURNS TABLE (street text, gid int, distance real)
LANGUAGE sql 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$;
大 tables 仍然不是很有效。您会对 KNN(k 最近邻)在 PostGis 中搜索感兴趣:
- Multicolumn index on 3 fields with heterogenous data types
- Improving performance with a Similarity Postgres fuzzy self join query
给定简单的 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
子句的变体,将其定义为行类型、记录甚至 table,但我总是得到示例中所示的元组或数组。关于如何以类似于 table?
尝试select * from foo(GeomFromText('POINT(-99.124191496999 19.3490666368031)',4326));
?..
问的问题已经回答了很多次了。分解返回的行类型:
SELECT * FROM foo( ... );
点赞:
但还有更多。
您的函数具有更少的语法混乱、更不容易出错和简化:
CREATE OR REPLACE FUNCTION foo (_point geometry)
RETURNS TABLE (street text, gid int, distance real)
LANGUAGE plpgsql 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$;
既然你有ORDER BY ... LIMIT 1
,你根本不需要min()
和GROUP BY
。
请注意我如何 table 限定所有列以避免命名冲突。
有一个细微差别:如果查询发现没有行你原来的returns一行用NULL值代替,而我的函数居然returns没有一行。通常,您会想要后者。
与等效的简单 SQL 函数相同:
CREATE OR REPLACE FUNCTION foo (_point geometry)
RETURNS TABLE (street text, gid int, distance real)
LANGUAGE sql 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$;
大 tables 仍然不是很有效。您会对 KNN(k 最近邻)在 PostGis 中搜索感兴趣:
- Multicolumn index on 3 fields with heterogenous data types
- Improving performance with a Similarity Postgres fuzzy self join query