2014-11-24 75 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