2014-11-24 110 views
1

基本上我无法理解plpgsql的语法,并希望得到一些有关以下工作的帮助。 我有一个包含1000个wgs84点的表格。下面的SQL将边框内检索的点的集合在此表:用于计算轴承的PLPGSQL函数

SELECT id, ST_X(wgs_geom), ST_Y(wgs_geom), ST_Z(wgs_geom) 
    FROM points_table 
    INNER JOIN 
    (SELECT ST_Transform(ST_GeomFromText('POLYGON((-1.73576102027 1.5059743629, 
    -1.73591122397 51.5061067655,-1.73548743495 51.5062838333,-1.73533186682 
     1.5061514313,-1.73576102027 51.5059743629))', 4326, 27700) 
    ) AS bgeom 
) AS t2 
ON ST_Within(local_geom, t2.bgeom) 

我需要做的是轴承/方位列添加到描述每个点在返回的数据承载结果组。 所以我试图实现的方法是构建一个plpgsql函数,可以根据上面的方式选择数据并计算循环中每组点之间的方位。然而,我在理解plpgsql函数内的基本数据访问和处理方面的努力却失败了。

的我试图创建函数的当前版本的一个例子如下:

CREATE TYPE bearing_type AS (x numeric, y numeric, z numeric, bearing numeric); 

--DROP FUNCTION IF EXISTS get_bearings_from_points(); 

CREATE OR REPLACE FUNCTION get_bearings_from_points() 
    RETURNS SETOF bearing_type AS 

$BODY$ 

DECLARE 
    rowdata points_table%rowtype; 
    returndata bearing_type; 

BEGIN 
    FOR rowdata IN 
     SELECT nav_id, wgs_geom 
      FROM points_table INNER JOIN 
      (SELECT ST_Transform(ST_GeomFromText('POLYGON((-1.73576102027 
       3.5059743629,-1.73591122397 53.5061067655,-1.73548743495 
       53.5062838333,-1.73533186682 53.5061514313,-1.73576102027 
       53.5059743629))', 4326), 27700) 
      AS bgeom) 
      AS t2 ON ST_Within(local_geom, t2.bgeom) 
    LOOP 
     returndata.x := ST_X(rowdata.wgs_geom); 
     returndata.y := ST_Y(rowdata.wgs_geom); 
     returndata.z := ST_Z(rowdata.wgs_geom); 
     returndata.bearing := ST_Azimuth(<current_point> , <next_point>) 
    RETURN NEXT returndata; 
    END LOOP; 
    RETURN; 
END 

$BODY$ 
LANGUAGE plpgsql; 

我想只调用这个函数如下:

SELECT get_bearings_from_points(); 

,并得到期望的结果。 基本上问题是理解如何正确访问rowdata,以便我可以读取当前和下一个点。

在上面的例子中,我遇到过如何调用ST_X等SQL函数时遇到的各种问题,并尝试使用带几何数据类型错误的EXECUTE select语句。

任何见解/帮助将不胜感激。

+0

这是不是真的清楚应该怎样wgs_geom指在你的程序中,我敢肯定, rowtype应该是bearing_type类型。无论如何,除此之外,你可以在不使用plpgsql的情况下完成所有这些。我很乐意将其写下来,除非你有一些要求在循环中完成这一切。 – 2014-11-24 21:43:44

回答

1

在PL/pgSQL中,尽可能多地尽可能多地处理基本的SQL查询是最有效的。你可以大大简化。

我没有得到的排序顺序的定义了你的问题,并留下???填写你:

CREATE OR REPLACE FUNCTION get_bearings_from_points(_bgeom geometry) 
    RETURNS TABLE (x numeric, y numeric, z numeric, bearing numeric) AS 
$func$ 
BEGIN 
    FOR x, y, z, bearing IN 
     SELECT ST_X(t.wgs_geom), ST_Y(t.wgs_geom), ST_Z(t.wgs_geom) 
      , ST_Azimuth(t.wgs_geom, lead(t.wgs_geom) OVER (ORDER BY ???)) 
     FROM points_table t 
     WHERE ST_Within(t.local_geom, _bgeom) 
     ORDER BY ??? 
    LOOP 
     RETURN NEXT; 
    END LOOP; 
END 
$func$ LANGUAGE plpgsql; 

window function lead()引用从按照排序顺序下一行一列。

这可以进一步被简化为一个单一的SQL查询 - 可能包裹成一个SQL函数:

CREATE OR REPLACE FUNCTION get_bearings_from_points(_bgeom geometry) 
    RETURNS TABLE (x numeric, y numeric, z numeric, bearing numeric) AS 
$func$ 
    SELECT ST_X(t.wgs_geom), ST_Y(t.wgs_geom), ST_Z(t.wgs_geom) 
     , ST_Azimuth(t.wgs_geom, lead(t.wgs_geom) OVER (ORDER BY ???)) 
    FROM points_table t 
    WHERE ST_Within(t.local_geom, $1) -- use numbers in pg 9.1 or older 
    ORDER BY ??? 
$func$ LANGUAGE sql; 

参数名称可以以pg 9.2或更高版本中被引用。 Per release notes of pg 9.2:

允许SQL语言函数按名称引用参数(马太福音 德雷珀)

+0

感谢您的答案,根据我的要求根据您的plpgsql解决方案工作,第二个选项给了我一个错误'No Column called _bgeom'。 – Diplonics 2014-11-25 17:04:04

+0

@Diplonics:对不起,这是第9.1页的限制。从9.2版开始,你可以在SQL函数的函数体中引用参数名称。相应地适应。 – 2014-11-25 20:34:42